Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECMAScript6-变量声明与变量的解构赋值 #24

Open
hubvue opened this issue Dec 26, 2018 · 0 comments
Open

ECMAScript6-变量声明与变量的解构赋值 #24

hubvue opened this issue Dec 26, 2018 · 0 comments

Comments

@hubvue
Copy link
Owner

hubvue commented Dec 26, 2018

通过阮大神ECMAScript6入门来聊一聊学习ES6了之后我觉得最值得关注的部分。

变量声明

在ES6之前声明一个变量或者声明一个函数都是用var来声明,深入了解javascript都知道,var是我们无法忘记的痛:变量提升,词法作用域,基于闭包的内存泄漏,这些在项目中忽然到来都让我们措手不及,懂得它们是什么原理还好,不懂得就会很懵逼。然而,ES6的到来在变量声明上为我们带来了福音,通过let和const基于块级作用域来定义变量弥补了javascript上“所谓“”的不足。

什么是块级作用域

在js代码中每一个成对花括号就代码一个块,就代表它自己所管辖的区域,通过let和const声明的变量存在指定的管辖区域内,只能由特定的块来管制。

{
    //这就是一个块,括号的内部就是块级作用域
}

ES6 允许块级作用域的任意嵌套。

{{{{{let insane = 'Hello World'}}}}};

let

通过let定义变量,它的用来类似于var,不同的是let声明的变量是基于块级作用域的,也就是说只能在声明变量所在的代码块中使用。

let str = "string";
let声明变量的特点
  1. 不存在变量提升

    我们都知道使用var声明的变量会存在变量提升,ES6中的let不存在变量提升

function test(){
    if(false){
        let a = 1;
    }
    console.log(a);     //error
}
  1. 暂时性死区(TDZ)

    什么是暂时性死区??ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

    也就是说,在一个块级作用域内,如果用let或者const声明了一个变量,那么从这个块级作用域顶部开始到声明这个变量之间的这部分区域就叫暂时性死区(TDZ)。在这个区域使用声明的这个变量会报错。

  2. 不允许重复声明

    let不允许在相同作用域内,重复声明同一个变量

const

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI = 3;     //会报错
console.log(PI)     //3.1415

const和let在特性有是相同的。

const的本质

const实际保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所存的数据是不变的。对于简单类型来说,值就保存在变量所指向的那个内存地址中,而对于引用类型来说,内存地址所保存的是指向实际数据的指针,至于它指向的数据结构是不是可变的,那就完全不能控制了。

const foo = {};
foo.name = "wang"       //给对象添加属性,只改变了对象内部的数据结构,内存地址没有改变。
foo = {};//error  给对象赋予一个新的值,改变了内存地址,因此报错。

变量的解构赋值

ES6新增了通过一种类似于模式匹配的方式来为变量赋值,这个东西就叫做解构。

数组的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值。

let arr = [1,2,3];
let [a,b,c] = arr;
console.log(a,b,c) //1  2  3

如果解构不成功,变量的值为undefined。

let [foo] = [];
console.log(foo)    //undefined

对于Set集合,也可以使用数组的解构赋值

let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"

数组解构的本质是:只要某种数据结构具有Iterator接口,就可以采用数组形式的解构赋值。

默认值

数组的解构是可以传入默认值的,当一个数组成员等于undefined(ES6采用严格相等运算符(===)来判断一个位置是否有值)的时候,默认值就会生效。

let [a = true] = [];
console.log(a) //true

对象的解构

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

如果变量名与属性名不一致,必须写成下面这样。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

实际上对象的解构赋值是下面形式的简写

let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。

函数参数的解构

函数的参数也可以使用解构赋值。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

函数参数的解构也可以使用默认值。

function move({x = 0, y = 0} = {}) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant