前言
感谢你能点进这篇文章,首先我先做一个说明,我是今年刚毕业的前端应届生,这篇文章是我学习ES6的let
和const
部分之后,自己做的归纳笔记,也是我的第一篇文章。第一次做这种文章类的分享,而且是在一个大平台上,如果有不足,希望可以帮我点出,十分感谢。
其实在发表文章之前,我们公司前端组的大佬就一直鼓励我去做文章分享,打造自己的一个品牌。但是由于自己性格问题和懒惰,一直在拖。毕竟我最开始并不觉得自己有什么能分享的,但是后续慢慢的才理解到一个真理:分享是没有门槛的。所以开始尝试做这种事情,希望可以慢慢做好,毕竟也是对自己的一种提升和锻炼。之后会继续更新ES6的学习记录文章,文章的内容,都是通过自己理解之后,然后用自己的话语去进行一个描述,当中可能会有不太准确或者不太恰当的描述,也欢迎观看文章的您提出这类的意见和建议。同时我的文章会进行一些内容的验证,有些部分可能会验证的有点多,也请多担待。
最后补充一句,我目前ES6系列学习的主要文献是阮一峰大神的《ECMAScript 6 入门》。
那就正式开始吧。
Let命令
let
命令用于声明变量,用法类似于var
,但是let
命令有个特点那就是只会作用在let
所在的作用域内。
Let命令的作用域
let a = 1;
{
var b = 2;
var c = a;
let d = 3;
}
a // 1
b // 2
c // 1
d // ReferenceError: b is not defined
这里的a
参数的let
命令用法毫无意义,如果这样使用就和var
没区别,倒不如说要这样使用还不如使用var
。
for
循环则非常适合使用该命令
for(let i=0;i<1;i++){
console.log('A',i);
}
console.log('B',i);
// A 0
// ReferenceError: i is not defined
在for
循环中使用let
命令,每一轮循环的i
都是一个新的变量,如果在内部使用计算公式等,则会通过JavaScript
引擎记住上一轮循环结果的值,然后对其进行后续的循环计算,总而完成计算。
for(let i = 0;i<3;i++){
let i = 'a';
console.log(i);
}
// a
// a
// a
此处是在
for
循环中使用let
时候的一个特点,当子作用域中使用let再次定义了一个与父作用域中相同名称的参数时,两个参数互不干扰。
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。
let a = 1;
let b = 1;
{
let a = 2;
b = 2;
console.log('a1',a);
console.log('b1',b);
}
console.log('a2',a);
console.log('b2',b);
// a1 2
// b1 2
// a2 1
// b2 2
当分别在父作用域和子作用域内使用
let
定义参数时,即便参数名相同,他们也不是同一个参数。父作用域中定义的参数,只会作用在自身作用域和未重新使用let
命令定义同名参数的子作用域中。该情况就是自作用于中的let
命令产生了暂时性死区。
var a = 1;
{
console.log(a)
let a = 2;
}
// ReferenceError: a is not defined
以上代码可知,作用域内只要使用了
let
命令声明的参数,即便有同名全局变量,也无法在let
命令代码执行之前对该参数进行任意操作,即使这个操作和let
命令是属于同一个作用域
let
的暂时性死区的特点, 会导致任意作用域,只要某个参数有对应的let
声明,无论该声明的位置在哪,该作用域内的该参数,便会完全独立于在该作用域内,不会受到全局或者父作用域中同名参数的干扰。
不允许重复声明
注意一点,let
命令是个小贪心鬼,同作用域内不允许有其他同名参数,无论是第二次同名命名是使用var
还是let
,都会报错。其子作用域中,也必须使用let
命令进行同名命名,否则也会报错。
let a = 1;
let a = 2;
console.log(a);
// Identifier 'a' has already been declared
var a = 1;
let a = 2;
console.log(a);
// Identifier 'a' has already been declared
let a = 1;
var a = 2
console.log(a);
// Identifier 'a' has already been declared
var a = 1;
var a = 2;
console.log(a);
// 2
let a = 1;
{
var a = 2;
console.log(a);
}
console.log(a);
以上代码若在
chrome
调试面板测试时,请切记手动改参数名或者清除上一次代码所命名的参数。
Let命令不存在变量提升
所谓变量提升,就是变量可以在声明代码之前使用,不会出现报错,不过值未undefined
,var
便有该特点。
console.log(a);
var a = 1;
// undefined
console.log(b);
let b = 1;
// Identifier 'b' has already been declared
使用
var
命令声明的参数,即会发生变量提升的参数,在脚本开始运行时,对应的变量就已经被创建,直到执行到实际定义参数的代码时,该参数才会被赋上对应的值。
块级作用域与函数声明
概念
在ES5中,一般只有全局作用域和函数作用域。
而在ES6中,增加了一个块级作用域。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
一般而言,每个{}
内部就是一个块级作用域。
function f() { console.log('I am outside!'); }
(function () {
if (false) {
function f() { console.log('I am inside!'); }
}
f();}());
// Uncaught TypeError: f is not a function
上述代码在ES6环境中执行的时候,会出现报错,因为两次声明的function
和执行的f()
不在同一块级作用域。
注意点
ES6改变了块级作用域内声明的函数的处理规则,但是由于互联网目前的现状是多个版本环境同时并行的情况。所以ES6有以下规定:
- 允许在块级作用域内声明函数
- 函数声明类似于
var
,即会提升到全局作用域或函数作用域的头部。 - 同时,函数声明还会提升到所在的块级作用域的头部。
以上规则只对ES6的浏览器生效。在其他环境下不会生效。
综上所述,我们需要尽量避免在块级作用域内声明函数。如果无法避免,也要写成函数表达式。并且块级作用域的声明函数规则,必须在使用{}
的情况下使用,不可以使用简写。
if(true)
function f() {}
//报错
const命令
概念
const
用于声明一个只读的常量。
特点
由于const
声明的常量为只读,所以其声明的常量无法修改。
const a = 123;
a //123
a = 321; // TypeError: Assignment to constant variable.
声明的常量不能再次修改,所以意味着他必须在声明的时候就进行赋值。因为如果不这样做,你的声明就没有意义。
const a; // SyntaxError: Missing initializer in const declaration
const
和let
相似,只在块级作用域内生效,同时也不提升和存在暂时性死区。
if(true){
const a = 1;
}
a // ReferenceError: a is not defined
if(true){
console.log(b);
const b = 1;
}
//ReferenceError: b is not defined
同时也和let
命令一样,在同一块级作用域内,不可重复使用一样的名称,即便一个是声明常量,一个是声明变量。
var a = 1;
let b = 1;
const a = 2; // SyntaxError: Identifier 'a' has already been declared
const b = 2; // SyntaxError: Identifier 'b' has already been declared
本质
const
并不是变量的值不可改变,而是变量所指向的那个内存地址所保存的数据不得改变。特别是复合类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const
只能保证指针是固定的。
听起来其实有点绕,我个人的理解是,比如你需要调某个仓库的货物,然后我告诉你仓库的地址,我只能保障那个仓库的位置在那里不变,但是仓库里面放什么我就无法保证了。
const a = {};
a.prop = 1;
a.prop; // 1
因此,使用const
声明的时候需要格外小心,不然就是红红的报错了。(虽然快过年了,但是代码还是别增添顾念的气氛了)
一些小补充
顶层对象的属性
在ES5中,顶层对象的属性和全局变量是等价的,也就是说全局变量的a = 1
等同于 window.a = 1
。
ES6中,为了改变这个情况,给var
和function
命令保留了原有的这个特性的同时。也规定了let
、const
和class
等命令所声明的全局变量,不属于顶层对象的属性。
var a = 1;
window.a //1
let b = a;
window.b //undefined
总结
第一篇结束了,一开始写的时候特别乱,然后慢慢调整成了目前这一篇。如果你觉得还可以,希望可以帮点个赞。之后的更新我会继续奉上,也希望能受到你的喜欢和收到你的意见和建议,十分感谢。