【JavaScript】解构赋值

1 作用于数组

1.1 解构赋值简介

解构赋值:按照一定的模式,从数组 / 对象中提取值,并对变量进行赋值

let [a, b, c] = [12, 5, 6]; // 左边的结构 = 右边的结构
console.log(a, b, c); // 12 5 6

本质上,这种写法属于 “模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值

变量 = 值
let [a, b, c] = [12, [5, 6]];
console.log(a, b, c); // 12 [ 5, 6 ] undefinedlet [a, [b, c]] = [12, [5, 6]];
console.log(a, b, c); // 12 5 6let [a, [[b], c]] = [1, [[2], 3]];
console.log(a, b, c); // 1 2 3
变量 < 值 - - - 不完全解构:左边模式,只匹配右边模式的一部分。这种情况下,仍可成功解构
let [, , c] = "baz";
console.log(c) // "z"let [x, , y] = [1, 2, 3];
console.log(x, y); // 1 3let [x, y] = [1, 2, 3];
console.log(x, y); // 1 2let [a, [b], c] = [1, [2, 3], 4];
console.log(a, b, c); // 1 2 4
变量 > 值 - - - 解构不成功,变量的值就等于 undefined
let [a] = []; // a 为 undefined
let [b, a] = [1]; // a 为 undefined
模式不匹配 - - - 报错 TypeError
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

1.2 默认值

我们可以给变量设置默认值,格式:变量名 = 默认值

let [a, b, c = "暂无数据"] = ["aa", "bb", "cc"]; // c 设置了默认值
console.log(a, b, c); // aa bb cclet [a, b, c = "暂无数据"] = ["aa"]; // b 没有默认值
console.log(a, b, c); // aa undefined 暂无数据

ES6 使用严格相等运算符 ===,来判断一个位置是否有值。所以,如果数值是 undefined,就会使用默认值

// 我们也可以选择性使用 undefined,来使用默认值
let [a, b = "暂无数据", c] = ["aa", undefined, "cc"];
console.log(a, b, c); // aa 暂无数据 cc// 如果传入的是 null,则不会使用默认值:undefined == null,undefined !== null
let [a, b = "暂无数据", c] = ["aa", null, "bb"];
console.log(a, b, c); // aa null bb
默认值可以是表达式

如果默认值是表达式,那这个表达式是惰性求值的,即只有在用到时,才会求值

function f() {console.log(2); // 不会输出return 2;
}let [x = f()] = [1];
console.log(x); // 1
  • 默认值生效时,才会调用 f()
function f() {console.log(2);return 2;
}let [x = f()] = [];
console.log(x); // 2 2
默认值可以是解构赋值的其他变量
let [x = 1, y = x] = [1, 2]; // x = 1;  y = 2
let [x = 1, y = x] = [2]; // x = 2;  y = 2
let [x = 1, y = x] = []; // x = 1;  y = 1
  • 被引用的变量必须是已经声明了的,否则会报错:
let [x = y, y = 1] = []; // ReferenceError: Cannot access 'y' before initialization

y=1 之前的区域为 y 的暂时性死区

作用:可以很方便地交换两个值
let a = 12, b = 5;
console.log(a, b); // 12 5
[a, b] = [b, a];
console.log(a, b); // 5 12



2 作用于对象

2.1 对象的解构赋值

  • 数组的元素是按次序排列的,变量的取值由它的位置决定
  • 对象的属性没有次序,所以属性名必须对应,才能取到正确的值
  • 对象的属性没有次序,所以不限获取的位置 & 次数
let obj = { // 定义对象name: "superman",age: 18
};let {name: nam,age: ag
} = obj;console.log(nam, ag); // superman 18
  • 对于对象,解构赋值的内部机制,是先找到同名属性,再赋值给对应的变量。真正被赋值的是后面的变量
  • 根据 ES6 的对象定义,属性名与变量名一样时,对象的解构赋值可以简写:
let {name: name,age: age,sex: sex
} = obj;console.log(name, age, sex); // superman 18 男
let {name,age,sex
} = obj;
  • 注意:对于对象,let 后面的 {} 是用于解构的,不会形成块级作用域,在同一作用域中不能重复 let
let a;
let { a } = { a: "apple" };  // SyntaxError: Identifier 'a' has already been declared

2.2 默认值

变量默认值生效的条件:属性值严格等于 === undefined

let { x = 3 } = {};
console.log(x); // 3

上述 {} 中没有 x 属性,默认给变量 x 赋值为 3

let { x, y = 5 } = { x: 1 };
console.log(x, y); // 1 5

上述 { x: 1 } 中,找到属性 x,再将属性值 1 赋值给变量 x;找不到属性 y,默认给变量 y 赋值为 5

let { x: y = 3 } = {}; // x 是属性名,y 才是变量
console.log(y); // 3

上述 {} 中,找不到属性 x,默认给变量 y 赋值为 3

let { x: y = 3 } = { x: 5 }; // x 是属性名,y 才是变量
console.log(y); // 5

上述 { x: 5 } 中,找到属性 x,将 属性值 5 赋给变量 y

2.3 数组的特殊解构

数组的本质是特殊的对象,所以可以对数组进行对象属性的解构

let arr = [1, 2, 3];
let { 0: first, [arr.length - 1]: last } = arr;
console.log(first, last); // 1 3
默认值可以是其他变量
let { x = 3, y = x } = {};
console.log(x, y); // 3 3



3 作用于基本类型的数据

3.1 字符串

  • 字符串有 length 属性,可以看做是类数组(对象)
const [a, b, c, d, e] = 'hello';
console.log(a, b, c, d, e) // h e l l o
  • 本质上,类数组是有 length 属性的对象,因此还可以对 length 属性进行解构赋值
let {length: len
} = 'hello';
console.log(len); // 5
  • 说明类数组可以使用正常的数组 / 对象的解构方式

3.2 数值、布尔值

let toString = Object.prototype.toString;
// 等价于
let {toString} = Object.prototype; // 对象的解构赋值
  • 解构赋值时,如果等号右边是数值 / 布尔值,会先转为包装类的对象
let { toString: s } = 123; // 123 转成对象 Number(123)
console.log(s === Number.prototype.toString) // truelet { toString: s } = true; // true 转成对象 Boolean(true)
s === Boolean.prototype.toString // true



4 作用于函数

4.1 配合函数参数

说到底就是数组 / 对象的解构赋值,只是写到函数参数的位置而已

  • 数组参数
function add([a, b]) {console.log(a + b);
}
add([2, 3]) // 5
  • 对象参数:
function fn({ a, b }) {console.log(a, b); // 1 2
}
fn({ a: 1, b: 2 })
对象参数的默认值 & 对象参数属性的默认值
function move({x = 0, // 对象参数的属性设置了默认值y = 0
} = {}) { // 对象参数设置了默认值console.log([x, y]);
}move({ x: 3, y: 8 }); // [3, 8]move({ x: 3 }); // [3, 0]// 因为对象参数的属性设置了默认值,所以可以传空对象
move({}); // [0, 0]// 因为对象参数设置了默认值,所以可以不传参
move(); // [0, 0]
  • 如果只有对象参数的默认值:
function move({ x, y } = { x: 0, y: 0 }) { // 这里只给对象参数设置了默认值return [x, y]; // 没有给对象参数的属性设置默认值
}move({ x: 3, y: 8 }); // [3, 8]move({ x: 3 }); // [3, undefined]// 没有设置对象参数的默认属性值,所以输出 undefined
move({}); // [undefined, undefined]// 需要不传参才能使用默认对象参数
move(); // [0, 0]

4.2配合函数返回值

function getPos() {return {left: 10,_top: 20 // top 是保留字,不能用作变量名};
}
let {left,_top
} = getPos();
console.log(left, _top); // 10 20



5 解构嵌套的结构

let obj = { // 解构对象,则按属性名赋值p: ['Hello',{y: 'World'}]
};let {p, // ["Hello", {…}]p: [a, b  // Hello {y: "World"}],p: [a, { // Helloy // World}]
} = obj;


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部