「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

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

相关推荐
祈澈菇凉1 小时前
Webpack的基本功能有哪些
前端·javascript·vue.js
小纯洁w1 小时前
Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
前端·webpack·node.js
想睡好2 小时前
css文本属性
前端·css
qianmoQ2 小时前
第三章:组件开发实战 - 第五节 - Tailwind CSS 响应式导航栏实现
前端·css
记得早睡~2 小时前
leetcode150-逆波兰表达式求值
javascript·算法·leetcode
zhoupenghui1682 小时前
golang时间相关函数总结
服务器·前端·golang·time
White graces2 小时前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea
庸俗今天不摸鱼2 小时前
Canvas进阶-4、边界检测(流光,鼠标拖尾)
开发语言·前端·javascript·计算机外设
菠菠萝宝2 小时前
【Java八股文】10-数据结构与算法面试篇
java·开发语言·面试·红黑树·跳表·排序·lru
bubusa~>_<3 小时前
解决npm install 出现error,比如:ERR_SSL_CIPHER_OPERATION_FAILED
前端·npm·node.js