「JS硬气功👊」JavaScript变量声明&&变量类型攻略🔪🔪

Hi!这里是JustHappy ,既然点开了这个JS硬气功,那就一起愉快的学习吧!我想大家都有在面试中碰到过JS变量类型之类相关的问题吧,今天我们来练一练这一块的,希望可以帮助大家和我自己在面试中把嘴皮子磨硬🪨🪨🪨

变量声明 && 变量类型 🐶🐮

var、let、const

letconst是ES6(ECMAScript 2015)引入的,旨在提供更好的作用域控制和变量声明的安全性。在现代JavaScript开发中,推荐使用letconst来代替var,以编写更清晰、更易于维护的代码。

为什么大家都不继续使用var?

var声明的变量会被提升到它们所在的作用域的顶部 (这怎么形容呢?就相当于在你代码的第一行前面声明了变量),但是它们的赋值不会提升

这是啥意思呢?我们来看看下面这几小段代码,大家也可以在自己的设备上跑一下

  • 我们尝试单独输出一个未被声明的变量
arduino 复制代码
console.log(myVal)
  • 显而易见,这行代码是会报错的

  • 但是如果我们在这行代码的下面使用var去声明这个变量,再在下面输出就会有以下情况

ini 复制代码
console.log(myVar); // 输出:undefined,而不是报错,因为变量声明被提升,但赋值没有提升
var myVar = 5;
console.log(myVar); // 输出:5
  • 我们都知道代码是顺序执行的,按道理说第一个console.log(myVal)应该会报错,但是却输出了undefined,这说明了该变量在这一行处于一个"被声明但是为被赋值的状态",而以上现象就是因为var变量的声明 被提升、但赋值并没有被提升

  • 这会导致什么问题呢?

    • 这可能导致在变量赋值之前就引用了未声明的变量,导致程序出现错误。

let和const

我们在使用let和const的时候是不存在变量提升这一问题,这是因为let和const声明变量会经历所谓的"暂时性死区"(Temporal Dead Zone,TDZ)

  • 下面两段代码也证明了这一点
ini 复制代码
console.log(letVal); // 抛出 ReferenceError: bar is not defined
let letVal = 'aaa';
ini 复制代码
console.log(constVal); // 抛出 ReferenceError: qux is not defined
const constVal = 'bbb';

你真的了解变量类型吗?

值类型 or 引用类型(即简单类型 和 复杂类型)

值类型 又或者说是 简单类型 吧,在JavaScript中有

我们先来看以下两段代码

ini 复制代码
// 值类型特征演示
let a = 10;
let b = a;
b = 20;
console.log(a); // 10

// 引用类型特征演示
let c = { name: "Jack" };
let d = c;
d.name = "Tom";
console.log(c.name); // Tom

很直观的可以看到值类型演示中原来的值没有被改变,但是在引用类型中却被改变了

所以这是为什么呢?

不只是JavaScript,几乎是所有的编程语言都有这个特性,这和数据在内存中的存储有关

在JavaScript中,值类型和引用类型在内存中的存储方式有显著的区别,这主要体现在它们存储的位置和访问方式上:

值类型(简单类型)
  1. 存储位置:值类型的数据直接存储在栈(stack)内存中。

  2. 存储方式:当值类型的数据被创建时,它们会直接被复制到栈中。例如,当你声明一个变量并赋予一个值时,这个值就会被存储在栈中。

引用类型(复杂类型)
  1. 存储位置:引用类型的数据存储在堆(heap)内存中。

  2. 存储方式:引用类型的变量实际上存储的是指向堆中数据的指针(引用)。当引用类型的数据被创建时,它们会被存储在堆中,而变量则保存了指向这些数据的引用。

那么对于一引用数据类型(复杂类型),我们用一个新的变量拷贝完再修改的话,如何使得原本的数据不被修改呢。于是乎我们来聊聊深拷贝浅拷贝

深拷贝和浅拷贝

由上我们知道,只有引用类型(复杂数据类型)需要进行深拷贝,所以在此之前我们需要掌握如何判断一个数据是否是引用类型,所以我们来看看typeof()

有关typeof()

typeof()可以直接返回简单数据类型的确切类型 ,而对复杂数据类型来说,则返回object ,对于函数则返回function,以下是返回结果示例

javascript 复制代码
// 对于简单数据类型
console.log(typeof 10); // number
console.log(typeof "Jack"); // string
console.log(typeof true); // boolean
console.log(typeof Symbol()); // symbol
console.log(typeof undefined); // undefined
//对于复杂数据类型
console.log(typeof {}); // object
console.log(typeof []); // object

//对于函数
console.log(typeof function () {}); // function

但是typeof()有个历史遗留问题,当判断null 的时候也会返回object

javascript 复制代码
console.log(typeof null); // object
所以我们来实现一个深拷贝吧!!!

实现深拷贝有多种方式,我们这里就写一种最重要的,最能体现编程思想的递归深拷贝

ini 复制代码
const deepClone = (obj) => {
  if (typeof obj !== "object" || obj === null) return obj;
  // 初始化反回结果
  let result;
  // 判断是数组还是对象
  if (Array.isArray(obj)) {
    result = [];
  } else {
    result = {};
  }
  for (let key in obj) {
    // 保证key不是原型链上的属性
    if (obj.hasOwnProperty(key)) {
      result[key] = deepClone(obj[key]);
    }
  }
  return result;
};

以下是测试这段代码的示例

css 复制代码
let e = {
  name: "Jack",
  sex: "male",
  address: {
    city: "Beijing",
  },
  age: 18,
};
let f = deepClone(e);

f.address.city = "Shanghai";
console.log(e); // { name: 'Jack', sex: 'male', address: { city: 'Beijing' }, age: 18 }
console.log(f); // { name: 'Jack', sex: 'male', address: { city: 'Shanghai' }, age: 18 }

有点烦人的变量类型转换

先看看以下几个示例吧

ini 复制代码
// 有关 "==" 号的类型转换

// 如果比较的两个值类型不同,js会尝试将它们转换为相同的类型。
console.log(3 == "3"); // true
console.log(true == 1); // true
console.log(false == 0); // true
console.log("" == 0); // true
console.log("" == false); // true
console.log(null == undefined); // true

// 但是NaN 不等于任何值,包括它自己
console.log(NaN == NaN); // false
console.log(NaN !== NaN); // true
console.log(NaN === NaN); // false

怎么样,是不是有些懵逼!😭

其实这只需要咱记住就好啦

那就有疑问了!我们该如何判断一个值是否是NaN 呢?该如何合乎逻辑的比较两个NaN呢?

我们可以使用 isNaN() 函数判断是否为NaN

javascript 复制代码
console.log(isNaN(NaN)); // true

使用 object.is() 函数判断两个值是否严格相等

javascript 复制代码
console.log(Object.is(NaN, NaN)); // true

如果有什么不足之处,大家尽管在评论区留言哦

相关推荐
庸俗今天不摸鱼20 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873021 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下27 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox37 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞40 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行40 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581041 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
uhakadotcom1 小时前
构建高效自动翻译工作流:技术与实践
后端·面试·github