对象的解构赋值
一、简介
数组的元素是按照次序排列的,变量的取值由它的位置决定。对象的属性没有次序,变量必须与属性同名才能取到正确的值
解构失败,变量的值等于undefined
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; foo // "aaa" bar // "bbb" let { baz } = { foo: 'aaa', bar: 'bbb' }; baz // undefined
对象的解构赋值,可以很方便的将现有对象的方法赋值到某个变量
// 例一 let { log, sin, cos } = Math; // 例二 const { log } = console; log('hello') // hello
上述代码将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上。将console.log赋值到log变量
对象的解构赋值是下面形式的简写方式:
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
对象的解构赋值的内部机制,是先找到同名属性,然后再赋值给对应的变量。真正赋值的是后者,前者是匹配的模式,后者才是真正的变量
即,下例:foo为匹配模式,baz才是变量。foo是去匹配值,baz被匹配到的值赋值
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" foo // error: foo is not defined
解构也可以用于嵌套结构的对象:
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 }} } = node; line // 1 loc // Object {start: Object} start // Object {line: 1, column: 5}
上述代码有三次解构赋值,分别对loc、start、line三个属性的解构赋值。注意!注意!最后一次对line属性解构赋值中,只有line是变量,loc和shart都是模式
// 报错 let {foo: {bar}} = {baz: 'baz'};
上例:foo匹配失败,foo等于undefined,再取子属性就会报错
对象的解构赋值可以取到继承的属性
const obj1 = {}; const obj2 = { foo: 'bar' }; Object.setPrototypeOf(obj1, obj2); const { foo } = obj1; foo // "bar"
上面代码中,对象obj1原型对象是obj2.foo属性不是obj1自身的属性,而是继承自obj2的属性。解构赋值可以取到这个值
歪个楼:Object.setPrototypeOf(obj, prototype)
obj:要设置其原型的对象
prototype:该对象的新原型(一个对象或null)
prototype参数不是一个对象或null(例如:数字,字符串,Boolean,或者undefined),则什么都不做。负责,该方法将obj的[[Prototype]]修改为新的值。
歪回来
二、默认值
指定默认值
var {x = 3} = {}; x // 3 var {x, y = 5} = {x: 1}; x // 1 y // 5 var {x: y = 3} = {}; y // 3 var {x: y = 3} = {x: 5}; y // 5 var { message: msg = 'Something went wrong' } = {}; msg // "Something went wrong"
默认值生效的条件是,对象的属性值严格等于undefined
var {x = 3} = {x: undefined}; x // 3 var {x = 3} = {x: null}; x // null
当属性x等于null,因为null与undefined不严格相等,所以是个有效的赋值,导致默认值3不会生效
三、注意点
1.如果要将一个已经声明的变量用于解构赋值,必须非常小心
// 错误的写法 let x; {x} = {x: 1}; // SyntaxError: syntax error
上面代码的写法会报错,因为 JavaScript 引擎会将{x}
理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
// 正确的写法 let x; ({x} = {x: 1});
2.解构赋值允许等号左边的模式中,不放置任何变量名
({} = [true, false]); ({} = 'abc'); ({} = []);
上面表达式毫无意义,但是语法是合法的
3.数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; first // 1 last // 3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通