前端百题斩【002】——js中6种变量声明方式

写该系列文章的初衷是“让每位前端工程师掌握高频知识点,为工作助力”。这是前端百题斩的第2斩,希望朋友们关注公众号“执鸢者”,用知识武装自己的头脑。

随着js的发展,目前共6种声明变量的方式,分别为var、let、const、function、class、import,下面分别阐述一下这六种方式。

1 var

在ES5阶段,用var定义变量,此阶段具有以下特点:

  1. 没有块的概念,可以跨块访问,不能跨函数访问;

  2. 存在变量提升。

// 代码没报错,而是打印出来了undefined,侧面说明了val变量存在变量提升
console.log(val); // undefined
var val = 1;
console.log(val); // 1

2 let

在ES6阶段,出现了块的概念,新增了块级作用域,同时新增了let命令,let声明的变量具有以下特点:

  1. let声明的变量只在它所在的代码块有效;

  2. 不存在变量提升。let不会像var那样会发生‘变量提升’现象,因此,变量需要先声明后再使用,否则会报错;

  3. 暂时性死区。在代码块内,使用let命令声明变量之前,该变量都是不可用的;

  4. 不允许重复声明。

// 实验一——只在所在的代码块有效
// 1
{
    let val = 2;
    console.log(val); // 2
}
// 2
{
    let val = 2;
}
console.log(val); // ReferenceError: val is not defined
// 实验2——不存在变量提升 + 暂时性死区
{
    console.log(val); // 报错
    let val = 2;
}
// 实验三——不允许重复声明
{
    let val = 1;
    let val = 2; // SyntaxError: Identifier 'val' has already been declared
}

3 const

在let命令出现的同时,出现了const命令,其用于声明一个只读的常量,具有以下特点:

  1. 一旦声明就必须立即初始化;

  2. 一旦声明,常量值就不能改变了(指的是内存地址不能改变);

  3. 块作用域内有效;

  4. 不存在变量提升;

  5. 存在暂时性死区。

对于上述的验证代码可以用参考let的。

对于const,还有一点比较有意思的指的详细阐述一下:const实际上保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。对于简单类型的数据而言,值就保存在变量指向的内存地址中,因此等同于常量。但对于复合类型的数据而言,变量指向的内存地址保存的只是一个指针,const只能保证这个指针是固定的,至于指向的数据结构不受控制。那么如何保证复合类型的值如何保证呢?可以使用Object.freeze()方法,该方法使对象的原始属性不可变,但仍然可以更改嵌套对象。为了使对象完全不可变,通过将嵌套对象上的所有属性冻结达到效果。

const constantize = obj => {
  Object.freeze(obj);
  Object.keys(obj).forEach( key => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

1.4 function

function命令用于定义一个函数,具有以下特点:

  1. 函数声明后不会立即执行,需要调用的时候才执行;

  2. 对支持ES5和ES6浏览器环境在块作用域内有一定区别,所以应避免在块级作用域内声明函数。

function test() {
 // ……
}

5 class

ES6语法引入了class关键字,用来定义类,该写法相比于对象原型的方式具有以下特点:

  1. 相比于对象原型的方式写法更清晰;

  2. 更像面向对象编程的语法(对有面向对象编程经验的同学更友好)。

class Calculate {
 constructor(x, y) {
  this.x = x;
  this.y = y;
 }
 
 add() {
  return this.x + this.y;
 }
}

6 import

ES6在语言标准的层面上实现了模块功能,其中import命令就是用于加载模块,然后输出变量,其具有以下特点:

  1. import命令接受一对大括号,其里面的变量名必须与被导入的模块对外接口的名称相同;

  2. 用as关键字可将输入的变量名重命名;

  3. import命令输入的变零都是只读的;

  4. import命令具有提升效果,会提升到整个模块的头部,首先执行(因为import命令是在编译阶段执行的,在代码运行之前);

  5. import是静态执行,不能使用表达式和变量;

  6. import会执行所加载的模块。

// 随便举个例子
import {add} from './calcluate';

7 有意思的小问题

下面四种情况分别输出什么?为什么呢?欢迎各位老铁留言

  1. 情况一

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
  1. 情况二

for (var i = 0; i < 3; i++) {
  var i = 'abc';
  console.log(i);
}
  1. 情况三

for (let i = 0; i < 3; i++) {
  var i = 'abc';
  console.log(i);
}
  1. 情况四

for (var i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}

1.如果觉得这篇文章还不错,来个分享、点赞、在看三连吧,让更多的人也看到~

2.关注公众号执鸢者,领取学习资料,定期为你推送原创深度好文

3.扫描下方添加进群,里面大佬多多,一起向他们学习

                           

1. 假如只剩下canvas标签

2. Vue源码思想在工作中的应用

3. 一文搞定Diff算法

4. 百度、小红书三面,均遇“赛马”问题

5. 十五张图带你彻底搞懂从URL到页面展示发生的故事

6. 一文搞懂Cookie、Storage、IndexedDB

7. 六张图带你从HTTP/0.9进化到HTTP3.0

8. (2.6w字)网络知识点灵魂拷问(上)——前端面试必问

9. (2.6w字)网络知识点灵魂拷问(下)——前端面试必问

10. 理论与API相结合理解Node中的网络通信

11. 硬核知识点——浏览器中的三类五种请求

12. 理论与实践相结合彻底理解CORS

13. 三步法解析Express源码

14. 一篇搞定前端高频手撕算法题(36道)

15. 十七张图玩转Node进程——榨干它

16. 理论与API相结合理解Node中的网络通信

17. 一文彻底搞懂前端监控

18. 前端的葵花宝典——架构

19. canvas从入门到猪头

20. 前端工程师的一大神器——puppeteer

21. 2021 年前端宝典【超三百篇】

22. 前端也要懂机器学习(上)

23. 前端也要懂机器学习(下)

24. 学架构助力前端起飞

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值