ES6变量解构赋值
分享变量解构分2部分
- ES变量的声明
- 变量的解构概念,用法,注意事项
- 可能在项目遇到的应用场景
第一部分变量的声明
ES6之前
大家都了解JavaScript 中变量作用域的基本单元一直是 function,就是函数作用域,
如果创建块级作用域的话就是要声明立即调用函数
// 全局作用域
var a = 2
// 块级作用域,
(function (){
var a = 3
console.log(a)
})()
console.log(a)
let 声明
es新增2个声明变量 let ,const方式, 只要在任意块里用这2个声明方式声明的都市块级作用域变量,
var,function声明的还是函数作用域变量,块的标志是{...}
这意味着我们只需要一对 { .. }
就可以创建一个作用域
var a = 2;
{
let a = 3
console.log( a ); // 3
}
console.log( a ); // 2
const 声明
用于创建常量。块级变量声明,这个变量的值在声明时设定之后就不允许改变。 const 声明必须要有显式的初始化。如果需要一个值为 undefined 的常量,就要声明 const a = undefined 。
{
const a = 2;
console.log( a ); // 2
a = 3; // TypeError!
}
块作用域函数
从 ES6 开始,块内声明的函数,其作用域在这个块内
{
foo(); // 可以这么做!
function foo() {
// ..
}
}
foo(); // ReferenceError
举个列子
a = 1, 每隔1秒输出a+1的值, 并赋值给a以此累加到值5为止
// 错误的
// 错误原因是 异步执行时去找 i变量,此时i的值为
for (var i = 1; i<=5;i++) {
setTimeout(function(){
console.log('i=>', i)
}, i*1000)
}
// 利用之前的块级作用域
for (var i = 1; i<=5;i++) {
(function (i){
// 原因相当于每次声明一个i 来实现块级
setTimeout(function(){
console.log('i=>', i)
}, i*1000)
})(i)
}
// 利用ES6的块级申明
for (let i = 1;i<=5;i++) {
// 相当于每次声明 i 在块内
setTimeout(function(){
console.log('i=>', i)
}, i*1000)
}
let,var,const注意事项
let,var 声明且未赋值时默认值undefined,const必须显示声明 不会默认undefined
let name = '张三',age
var _name = '李四',_age
const __name = '王五', __age // 报错
let ,const 不允许重复声明
let a = 1
let a = 2 // 报错
let ,const 必须声明后使用,如在声明前调用会报错,var声明前使用值默认为undefined
console.log(a) // undefined
console.log(b) // 报错
var a = 0
let b = 1
连续声明赋值可采用数组解构
- 对象
- 数组
- 字符串
- 数字
- 布尔
- 类数组 (arguments,Dom对象)
1 . set, map
其中字符串,数字,布尔都会有个转成对象的过程
第二部分变量解构
把这个功能看作是一个结构化赋值(structured assignment)方法
1.什么变量可解构?
2. 何时赋值?
3. 赋什么位置的值?
什么变量可使用赋值解构
可遍历的对象
对象解构
我们构造了一个手动赋值,把 foo() 返回对象中的值赋给独立变量 x 、 y 和 z ,
为了实现这一点,我们(不幸地)需要一个临时变量 tmp 。
之前
function bar() {
return {
x: 4,
y: 5,
z: 6
};
}
var tmp = bar(),
x = tmp.x, y = tmp.y, z = tmp.z;
console.log( x, y, z ); // 4 5 6
tmp.x 属性值赋给了变量 x ,同样地, tmp.y 赋给了 y , tmp.z 赋给了 z 。
之后
function bar() {
return {
x: 4,
y: 5,
z: 6
};
}
var { x, y, z } = bar();
console.log( x, y, z ); // 4 5 6
// 这里可体现啦,对象赋什么位置上的值
var {x: ban, z: bap, y: baz,} = bar()
console.log(ban,bap,baz) // 4 6 5
// 先用x标识去右边对象找到值 --> 然后把值付给ban变量, source = target
// 刚好与什么对象指定值相反 --> target = source
var testObj = {
ban: x,
bap:z,
baz:y
}
// 所以上面的实则是
var { x:x, y:y, z:z } = bar();
// 完全体现把对象赋给数组
var o1 = { a: 1, b: 2, c: 3 },
a2 = [];
( { a: a2[0], b: a2[1], c: a2[2] } = o1 );
console.log( a2 ); // [1,2,3]
对象嵌套解构
var o1 = { x: { y: { z: 6 } } };
var { x: { y: { z: w } } } = o1;
console.log( w ); // 6
不只是声明
在已经声明的变量中应用解构赋值就是赋值操作,不只是声明
var bar = {x: 4, y: 5,z: 6}
var x , y, z
( { x, y, z } = bar );
console.log( x, y, z ); // 4 5 6
如果省略了 var/let/const 声明符,就必须把
整个赋值表达式用 ( ) 括起来。因为如果不这样做,语句左侧的 {..} 作为语
句中的第一个元素就会被当作是一个块语句而不是一个对象
赋值表达式 ( x 、 y ,z等 ) 并不必须是变量标识符。任何合法的赋值表达式都可以。
举个栗子
var o = {x:88,y:88,z:88};
( { x: o.x, y: o.y, z: o.z } = bar() );
console.log( o.x, o.y, o.z ); // 4 5 6
可以在解构中使用计算出的属性表达式
举个例子( 应用场景 )
var which = "x",
o = {};
( { [which]: o[which] } = bar() );
console.log( o.x );
注意事项
对象的解构的值包括继承对象
function Parent(){
this.child = 'child'
}
Parent.prototype = {
parent: 'parent'
}
// 在Object.prototype上有hasOwnProperty
var obj = new Parent()
var {child,parent,hasOwnProperty} = obj
console.log(child, parent, hasOwnProperty)
数组的解构赋值
赋何值 --> 数组中提取值,按照对应位置,对变量赋值
以前,为变量赋值,只能都是指定值
let a = 1;
let b = 2;
let c = 3;
ES6 允许写成下面这样。
let [a, b, c] = [1, 2, 3];
嵌套数组进行解构
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo,bar,baz) // 1,2,3
默认赋值
默认参数值
多年以来我们实现这一点的方式是这样的,
function foo(x,y) {
x = x || 11;
y = y || 31;
console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17 null被强制转换成0 11+6
foo( 0, 42 ); // 53 <--哎呀,并非42
es6 默认参数值
function foo(x = 11, y = 31) {
console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- 丢了undefined
foo( 5, null ); // 5 <-- null被强制转换为0
foo( undefined, 6 ); // 17 <-- 丢了undefined
foo( null, 6 ); // 6 <-- null被强制转换为0
foo( 0, 42 ); // 42
知识点: 在函数声明中的 x = 11 更像是 x !== undefined ? x : 11 而不是常见技巧 x || 11 ,所以
在把前 ES6 代码转换为 ES6 默认参数值语法的时候要格外小心。
再来看解构赋值的默认值
// 全为undefined时
var obj = []
var [a = 3, b = 6, c =7] = obj
console.log(a,b,c) // 3,6,7
// 验证
var obj = [null, false,undefined,NaN,0]
var [a = 1,b = 1,c = 1,d = 1,e = 1] = obj
console.log(a,b,c,d,e) // 只有c为 1
字符串解构
var str = '你好世界'
var[a,b,c,d,length] = str
console.log(a,b,c,d,length) // 你 好 世 界 4
// 中间实际有一个转换过程
var strObj = new String('你好世界')
var [aa,bb,cc,dd,length] = strObj
console.log(aa,bb,cc,dd,length)
数值的解构
var num = 1234
var {toString: s}= num
console.log(s)
// 中间实际有一个转换过程
var numObj = new Number(1234)
var {toString: s} = numObj
布尔的解构
var bool= false
var {toString: s}= bool
console.log(s)
// 中间实际有一个转换过程
var boolObj = new Boolean(1234)
var {toString: s} = boolObj
console.log(s)
第3部分项目中应用
- 交换变量的值
在项目中我们可能会要备份一份数据来,处理逻辑
之前
let a = '你好',b = '世界'
console.log(a,b)
a = [a,b];
b = a[0];
a = a[1];
console.log(a,b)
es6
let a = '你好',b = '世界';
console.log(a,b);
[a,b] = [b,a];
console.log(a,b);
- 需缓存重置数据时
(应用场景resetCom) - 提取后台接口参数
(应用场景apiCom)