ES6声明变量的六种方式:
ES5只有两种声明变量的方法: var
命令和function
命令.ES6除了let
和const
命令,另外还有import
和class
声明方式.ES6一共有6种声明变量的方法. (还有var定义的变量存在变量提升)
CONST命令定义常量相关
const
声明一个只读的常量.一旦声明,常量的值就不能改变.
const
声明的变量不得改变,这就意味着,const
一旦声明变量,就必须立即初始化,不能留到后面赋值.
const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动.对于简单类型的数据(数值,字符串,布尔值),值就保存在变量指向的那个内存地址.因此等同于常量.但是对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const
只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了.
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
顶层对象的属性相关:
顶层对象,在浏览器环境指的是window
对象,在Node指的是global
对象.在ES5之中,顶层对象的属性与全局变量是等价的.
ES6为了改变这一点,一方面规定,为了保证兼容性,var
命令和function
命令声明的全局变量,依旧是顶层对象属性.另一方面规定,let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
数组和对象的结构赋值
1.数组的解构赋值:
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [a,b,c] = [1,2,3];
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
2.对象的解构赋值:
解构不仅可以用于数组,还可以用于对象.
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
对象的解构与数组有一个重要的不同.数组的元素是按照次序排列的,变量的取值由他的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值.
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于undefined
。
有时候在工作中会遇到多层解构赋值,例如如下代码:
async getIconcate() {
let res = await api.getIndexIcon({ terminal: 0 });
const {
//resultContent: { resultContent },
resultContent: { resultContent:resData },
resultFlag,
resultMsg
} = res.data;
if (resultFlag) {
this.insuranceTypes = resData;
//this.insuranceTypes = resultContent.slice(0,5);
} else {
toToast(resultMsg);
}
// console.log('resData',resData);
//return resultContent
return resData;
}
使用babel转换后的代码如下:
与数组一样,解构也可以用于嵌套解构的对象.
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
注意,这时p
是模式,不是变量,因此不会被赋值.如果p
也要作为变量赋值,可以写成下面这样.
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
下面是另外一个例子.
const node = {
loc:{
start:{
line:1,
column:5
}
}
}
let { loc, loc: { start }, loc: { start: { line,column }} } = node;
console.log(line,column); //1 5
line //1
loc //Object {start:Object}
start //Object {line:1,column:5}
函数参数的解构赋值
function add([x,y]){
return x+y;
}
add([1,2]); //3
在上面的代码中,函数add
的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x
和y
,对于函数内部的代码来说,他们能感受到的参数就是x
和y
解构赋值的一些用途
(1).交换变量的值:
let x = 1;
let y = 2;
[x, y] = [y, x];
(2).从函数返回多个值:
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回.有了解构赋值,取出这些值就非常方便.
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
(3).函数参数的定义
解构赋值可以方便的将一组参数与变量名对应起来.
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
(4).解构赋值对提取JSON对象中的数据,尤其有用.(接口联调中经常这么用)
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
(5).函数参数的默认值
jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
} = {}) {
// ... do stuff
};
指定参数的默认值,就避免了在函数体内部在写var foo = config || 'default foo'
;这样的语句.