找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2073

积分

0

好友

290

主题
发表于 昨天 04:28 | 查看: 6| 回复: 0

这是一道字节面试题,大家第一眼看到这个面试题的时候,是不是觉得既熟悉又陌生?我当时也是一样的感受。

在 JavaScript 中,解构赋值语法的左侧是一个数组,而右侧则应该是一个具有迭代器接口的对象(如数组、Map、Set等)。因此,将对象 {a: 1, b: 2} 解构赋值给 [a, b] 会导致语法错误,但面试官偏偏要求我们让这个表达式成立。

思路

错误思路

既然将一个对象解构赋值给数组会报错,那我们直接把这个解构语法变为对象的解构赋值语法不就好了?比如改成 var { a, b } = { a: 1, b: 2 };。如果真这么做,恭喜你,面试可能就到此结束了。

所以我们得好好想清楚,这道题考察的绝不是表面这么简单。

正确解题思路

我们首先来看看具体的报错信息:

var [a, b] = {a: 1, b: 2}
TypeError: {(intermediate value)(intermediate value)} is not iterable

这个错误明确指出右侧的对象是不可迭代的。这提示我们,题目的核心是考察对迭代器的理解。

我们可以通过一个对比场景来加深理解:

let arr = [1, 2, 3]
let obj = {
    a: 1,
    b: 2,
    c: 3
}
for(let item of arr){
    console.log(item) // 输出:1, 2, 3
}
for(let item of obj){
    console.log(item) // 报错:TypeError: obj is not iterable
}

我们知道 for...of 循环只能遍历具有迭代器接口的数据结构。遍历数组没有问题,但遍历对象就会报错。那么,数组的迭代器属性到底是什么样的呢?

JavaScript 数组原型方法列表截图

我们可以在数组的原型链上找到 Symbol.iterator 这个属性。这个属性的值是一个函数,如果我们调用它看看:

console.log(arr.__proto__[Symbol.iterator]());
// 输出:Object [Array Iterator] {}

最关键的点来了 🔥

它返回的是一个迭代器对象!所以,一个可迭代对象的基本结构是这样的:

interable
{
    [Symbol.iterator]: function () {
        return 迭代器 // 一个具有 next() 方法的对象
    }
}

我们可以得出结论:只要一个数据结构拥有 [Symbol.iterator] 属性,且其值是一个能返回迭代器对象的函数,那么这个数据结构就是可迭代的。

回到面试题,要让 var [a, b] = {a: 1, b: 2} 成立,思路就很清晰了:我们需要手动为对象添加一个迭代器接口。换句话说,就是让对象的原型继承到迭代器属性。

我们可以先尝试一下:

Object.prototype[Symbol.iterator] = function(){

}

var [a, b] = {a: 1, b: 2}
console.log(a, b);

这时,错误信息变了:

TypeError: Result of the Symbol.iterator method is not an object

这说明我们定义的函数没有返回一个正确的迭代器对象。我们知道 var [a, b] = [1, 2] 是完全可以的,因此我们可以将对象身上的迭代器,模拟成和数组的迭代器一样。一个巧妙的实现是利用 Object.values() 方法:

Object.prototype[Symbol.iterator] = function(){
    // 使用 Object.values(this) 获取对象的所有值,并返回这个值数组的迭代器
    return Object.values(this)[Symbol.iterator]()
}

这段代码重写了 Object.prototype 上的 [Symbol.iterator] 方法。新方法通过 Object.values(this) 获取当前对象的所有属性值(形成一个数组),然后直接返回这个值数组的迭代器。

完成这一步后,最初的面试题就能成功执行了:

var [a, b] = {a: 1, b: 2};
console.log(a, b); // 输出:1 2

通过这个修改,我们使得任何 JavaScript 对象都具备了可迭代的能力。现在,你不仅可以对对象使用数组解构,甚至可以用 for...of 循环来遍历它的值,这正是 ES6+ 中迭代器协议的强大之处。

看到这里,恭喜你成功拆解并解决了一个字节的面试题!在面对这类“熟悉又陌生”的问题时,关键在于理解其背后的核心概念,比如这里的迭代器协议。希望这个解析能帮助你更好地掌握 JavaScript 的高级特性。




上一篇:Java分页查询结果不稳定?详解数据库排序与MyBatis Plus实战解决方案
下一篇:信创产业全解析:核心技术、产业链布局与国产化发展现状
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 13:59 , Processed in 0.195946 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表