文 / 景朝霞
来源公号 / 朝霞的光影笔记
ID / zhaoxiajingjing
❥❥❥❥点个赞,让我知道你来过~❥❥❥❥
ES6 慢慢学~
1 /
ES5 只有两种声明变量的方法:var
命令和function
命令。
ES6 除了添加let
命令和const
命令,另外两种声明变量的方法:import
命令和class
命令。
所以,ES6一共有6 种声明变量的方法。
-
var
命令可以声明变量 -
function
命令声明函数,后跟一组参数及函数体 -
let
命令用于声明变量 -
const
命令声明一个只读的常量 - 通过
export
命令显式指定输出的代码,再通过import
命令输入 -
class
关键字可以定义类
2 /
let
命令和const
命令所声明的变量or常量只在它所在的代码块有效。
const
实际上保证的,并不是变量的值不得改动,而是变量指向的按个内存地址所保存的数据不得改动。
- 对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
- 对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针。
const
只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。const
只声明不赋值,就会报错。
for (let i = 0; i < 4; i++) {
// ...
}
console.log(i);
// ReferenceError: i is not defined
const student = {};
// 可以添加一个属性
student.name = '朝霞的光影笔记';
// 将 student 指向另一个对象,就会报错
student = {}; // TypeError: "student" is read-only
3 /
ES5 只有全局作用域和函数作用域,没有块级作用域,这样会有一些不合理的场景。
- 内层变量可能会覆盖外层变量
- 用来计数的循环变量泄露为全局变量
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'zhaoxiajingjing';
}
}
f(); // undefined
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
ES6 新增了块级作用域,允许任意嵌套。使得自执行匿名函数表达式就不再必要了。
{{{{
{let insane = 'zhaoxiajingjing'}
console.log(insane); // 报错
}}}};
// 自执行匿名函数
(function () {
var tmp = ...;
}());
// 块级作用域写法
{
let tmp = ...;
}
4 /
只要块级作用域内存在let
命令或const
命令,它所声明的变量或常量就“绑定”(binding)这个区域,不再受外部影响。
在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为:暂时性死区(temporal dead zone,简称TDZ)
if (true) {
// TDZ开始
tmp = 'zhaoxiajingjing'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
5 /
let
和const
PK var
- 有效范围:
var
声明的变量,会声明到全局,污染全局变量- 变量提升:
var
声明的变量,可以在声明之前调用- 作用域:使用
var
的作用域有全局作用域、函数作用域- 重复声明:
var
能重复声明
1.有效范围
let
和const
只在声明所在的块级作用域内有效var
声明的变量,会声明到全局,污染全局变量
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
window.a[4](); // 10
window.i; // 10
上面代码中,变量 i
是var
命令声明的,在全局范围内有效,所以全局只有一个变量i
。可以在window
上访问并获取到值。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
window.a[4](); // 4
window.i; // undefined
上面代码中,变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
都是一个新的变量,所以每次输出的值不一样。
let
声明的变量仅在块级作用域内有效,所以在window
上i
的值是undefined
。
for
循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'zhaoxiajingjing';
console.log(i);
}
// zhaoxiajingjing
// zhaoxiajingjing
// zhaoxiajingjing
2.变量提升
let
和const
声明的变量or常量不会提升,一定要在声明后使用,否则报错var
声明的变量,可以在声明之前调用,值为undefined
// var 的情况
console.log(a); // 输出undefined
var a = 2;
// let 的情况
console.log(b); // 报错ReferenceError
let b = 2;
3.作用域
let
和const
可以在块级作用域中使用- 使用
var
的作用域有全局作用域、函数作用域
{
var a = 'hello';
let gzh = 'zhaoxiajingjing';
}
console.log(a); // hello
console.log(gzh); // ReferenceError: gzh is not defined
4.重复声明
let
和const
不允许在相同作用域内,重复声明同一个变量var
能重复声明
// 报错
function f(){
let gongzhonghao = 'zhaoxiajingjing';
var gongzhonghao = 'zhaoxiajingjing';
}
f();
// 不报错
function f(){
var gongzhonghao = 'zhaoxiajingjing';
var gongzhonghao = 'zhaoxiajingjing';
}
f();
// 报错
function f(args){
let args = 'zhaoxiajingjing';
}
f();
// 不报错
function f(args){
{
let args = 'zhaoxiajingjing';
}
}
f();
思考 /
- 函数能不能在块级作用域之中声明?
- 暂时性死区对
typeof
有什么影响?
参考:ECMAScript 6 入门
http://es6.ruanyifeng.com/#do...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。