初步学习后,发现确实内容太多,最近一周被跳槽的事情所影响,加之工作上的任务确实很重(算是个借口吧),精力有限,没有将所有的内容整理完,姑且这里先把最基础最好整理的一些知识点扔上来,令各位催更的好朋友们失望了,我会近期把剩余零散的笔记整理出来供大家学习参考。各位万分抱歉!
基础特性
1、let只在声明的代码块内有效;
var a = [];
for (var i = 0; i
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
var a = [];
for (let i = 0; i
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
2、有意思的for循环内存分配
for循环中,循环体内部的作用域和定义循环变量的作用域是分别独立的两个作用域,每一轮循环的变量i,都是重新声明的,只不过js引擎会记录上一次循环变量的i值;
for (let i = 0; i
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
3、变量不必要提升
变量提升的描述大致是块级作用域内的变量适用区域扩展到了块级作用域外;
// var的情况
console.log(foo); //输出undefined
var foo = 2;
// let的情况
console.log(bar); //报错ReferenceError
let bar = 2;
变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。
4、暂时性死区
暂时性死区的描述是,在代码块内,使用let、const命令声明变量之前,该变量都是不可用的,否则会报语法错误,这种特性叫暂时性死区。
function bar(x = y, y = 2){
return [x, y];
}
bar(); //报错
Let和Const的暂时性死区概念被ES6引入的目的是防止运行时错误,防止在变量声明前使用的情况发生,其本质是在进入当前作用域,所有要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量(有点类似于“半个”静态变量,编译时分配了地址,但却没有指定类型,不可以用,但已知存在,更形象点是买了车,在没有车钥匙前,只能看到但不能使用)
5、在同一个块级作用域(下面会有介绍)中不允许重复声明一个已知的变量
块级作用域
1、什么是块级作用域:
看完诸多例子后,我的理解就是“{}”所囊括的区间即为一个块级作用域;
2、ES5与ES6关于块级作用域的区别在哪里:
ES5只有全局作用域和函数作用域,没有块级作用域,由于变量提升的影响,很可能会出现内层变量覆盖外层变量的情况,或是循环中用于计数的变量泄漏为全局的变量,影响后面逻辑;
var s = 'hello';
for (var i = 0; i
console.log(s[i]);
}
console.log(i); // 5
函数声明与块级作用域的关系
首先我对自己的表达能力里不够自信,这部分的示例讲解大部分采用阮一峰老师的表述。
1、函数声明究竟能不能在块级作用域中进行?
ES5只可以在顶层作用域或函数作用域中声明,ES6明确规定可以在块级作用域中声明;
2、ES6中,引入块级作用域,函数声明语句行为类似于let,在块级作用域之外是不可以使用的,如下例子:
function f() { console.log('I am outside!'); }
(function () {
if (false) {
//重复声明一次函数f
function f() { console.log('I aminside!'); }
}
f();
}());
理论上按照ES6的标准,在浏览器中这里是应该输出“I am outside!”的,因为 If 语句内部重新声明的函数 f 作用域仅在 If 语句内部有效, 而在ES5标准的浏览器中则会将 If 语句声明的函数 f 提升到函数头部,最终演变成如下代码
// ES5环境
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I aminside!'); }
if (false) {
}
f();
}());
结果输出“I am inside!”,事实上在ES6中会报错,是不是有点不可思议!
3、浏览器又搞特殊了,明白点?
好吧,咱们来个例子:
//情况一
if (true) {
function f() {}
}
//情况二
try {
function f() {}
} catch(e) {
// ...
}
上述两种情况在ES5标准下是都会报错的,但实际上,浏览器并没有遵守这个规定,为了兼容旧代码,ES6在附录B里面规定:
浏览器可以不遵守上述规定,可以有自己的行为方式:
允许在块级作用域内声明函数。
函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。
当然,以上三条也仅仅是针对ES6的浏览器环境有效,其他环境的实现可以不遵守,还是将块级作用域的函数声明当做let处理。
所以,为了避免环境导致的行为差异太大,应该避免再块级作用域内声明函数,如果确实需要,也应该写成函数表达式,而不是函数声明语句。(但Ts我试过就完全不用有这些顾虑)具体操作如下:
//函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
//函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
CONST
Const其实和常规的语言无二,基本上记住两个特性就好了:
1、常量,故声明必赋值;
2、同样存在暂时性死区,未定义前不可使用;
喜欢分享学习和交流心得的朋友可以关注我的公众号,多多指教,共同进步!
下期预告:
ES6 学习笔记 - Js在内存中的玩法、变量的结构赋值
领取专属 10元无门槛券
私享最新 技术干货