大厂面试真题:在不修改下面代码的情况下,如何使得该代码成立?
ts
const [a,b] = {
c:1,
d:2
}
console.log(a,b) // 1 2
解构
首先来看看下面这行代码
js
const [a,b] = [1,2]
console.log(a,b) // 1 2
const {c,d} = {
c:3,
d:4
}
console.log(c,d) // 3 4
显而易见,这行代码大家都能看懂,但如果换成下面这行代码呢?
js
const {c,d} = {
e:3,
f:4
}
console.log(c,d) // undefined undefined
这种写法属于对象的解构赋值,其原理是:
在解构赋值时,JavaScript 会根据变量名(如 c、d)去右侧对象中查找同名属性,并将对应的属性值赋给变量。对象解构赋值本质上是通过属性名的匹配来完成的,而不是依赖于对象的迭代器或顺序。
所以这里可以解构,是因为对象字面量 {c:3, d:4} 拥有 c 和 d 两个属性,解构赋值语法会自动将它们提取出来赋值给同名变量。
迭代器
1. 什么是迭代器?
定义:在 JavaScript 中,迭代器是一个对象,它定义一个序列,并在终止时可能附带一个返回值。
更具体地说,迭代器是通过使用 next()
方法实现了迭代器协议的任何一个对象,该方法返回具有两个属性的对象:
js
console.log(Array[Symbol.iterator]) // [GeneratorFunction (anonymous)]
console.log(Array[Symbol.iterator]()) // Object [Generator] {}
console.log(Array[Symbol.iterator]().next()) // {value: undefined, done: true}
所以这里就能理解:
js
const [a,b] = [1,2]
console.log(a,b) // 1 2
数组解构的本质是:
js
const [a,b] = [1,2]
// 相当于
const arr = [1,2]
const iterator = arr[Symbol.iterator]()
const a = iterator.next().value
const b = iterator.next().value
console.log(a,b) // 1 2
回归题目
如何使得其成立,相信大家应该心理已经有思路和答案了
ts
const [a,b] = {
c:1,
d:2
}
console.log(a,b) // 1 2
- 对象的原型上是没有
[Symbol.iterator]
这个方法的
js
console.log(Array.prototype[Symbol.iterator]) // [Function: values]
console.log(Object.prototype[Symbol.iterator]) // undefined
这里只需要给Object
的原型上实现这个迭代器方法
就可以,具体如下⬇️
ts
// 方法1: 手动迭代器实现
Object.prototype[Symbol.iterator] = function(){
const keys = Object.keys(this) // Object.keys() 使用属性创建顺序(ES2015+规范)
let index = 0
return {
next:()=>{
if(index < keys.length){
return {
value: this[keys[index++]],
done: false
}
}else{
return {
value: undefined,
done: true
}
}
}
}
}
// 方法2:生成器函数实现(推荐)
Object.prototype[Symbol.iterator] = function*(){
for(const key of Object.keys(this)){
yield this[key];
}
}
迭代器协议工作流程

JavaScript的设计哲学
"如果它像鸭子一样走路和叫,那它就是鸭子" - 鸭子类型
- 协议驱动:只要对象实现了迭代接口,就能被当作可迭代对象
- 解构本质:数组解构是迭代器语法糖,不要求原始数据结构