2
文 / 景朝霞
来源公号 / 朝霞的光影笔记
ID / zhaoxiajingjing
❥❥❥❥点个赞,让我知道你来过~❥❥❥❥

ES6 慢慢学~

1 /

ES5 只有两种声明变量的方法:var命令和function命令。

ES6 除了添加let命令和const命令,另外两种声明变量的方法:import命令和class命令。

所以,ES6一共有6 种声明变量的方法

我在这与你共同进步

  1. var命令可以声明变量
  2. function命令声明函数,后跟一组参数及函数体
  3. let命令用于声明变量
  4. const命令声明一个只读的常量
  5. 通过export命令显式指定输出的代码,再通过import命令输入
  6. 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 只有全局作用域和函数作用域,没有块级作用域,这样会有一些不合理的场景。

  1. 内层变量可能会覆盖外层变量
  2. 用来计数的循环变量泄露为全局变量
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

看10遍不如写1遍

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 /

letconstPK var
  1. 有效范围var声明的变量,会声明到全局,污染全局变量
  2. 变量提升var声明的变量,可以在声明之前调用
  3. 作用域:使用var的作用域有全局作用域、函数作用域
  4. 重复声明var能重复声明
1.有效范围
  • letconst只在声明所在的块级作用域内有效
  • 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

上面代码中,变量 ivar命令声明的,在全局范围内有效,所以全局只有一个变量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

上面代码中,变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i都是一个新的变量,所以每次输出的值不一样。

let声明的变量仅在块级作用域内有效,所以在windowi的值是undefined

for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
    let i = 'zhaoxiajingjing';
    console.log(i);
}
// zhaoxiajingjing
// zhaoxiajingjing
// zhaoxiajingjing
2.变量提升
  • letconst声明的变量or常量不会提升,一定要在声明后使用,否则报错
  • var声明的变量,可以在声明之前调用,值为undefined
// var 的情况
console.log(a); // 输出undefined
var a = 2;

// let 的情况
console.log(b); // 报错ReferenceError
let b = 2;
3.作用域
  • letconst可以在块级作用域中使用
  • 使用var的作用域有全局作用域、函数作用域
{
    var a = 'hello';
    let gzh = 'zhaoxiajingjing';
}
console.log(a); // hello
console.log(gzh); // ReferenceError: gzh is not defined
4.重复声明
  • letconst不允许在相同作用域内,重复声明同一个变量
  • 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();

zhaoxiajingjing

思考 /

  1. 函数能不能在块级作用域之中声明?
  2. 暂时性死区对typeof有什么影响?
参考:ECMAScript 6 入门
http://es6.ruanyifeng.com/#do...

公号首发:朝霞的光影笔记


Pink
269 声望14 粉丝

没有什么是20遍解决不了的,如果有~那就再写20遍