8 个有趣的 JavaScript 题目
1、sort
const arr1 = ['a', 'b', 'c'];
const arr2 = ['b', 'c', 'a'];
console.log(
arr1.sort() === arr1,
arr2.sort() == arr2,
arr1.sort() === arr2.sort()
);
Answer: true, true, false
首先,array sort
方法对原始数组进行排序,并返回对该数组的引用。这意味着在编写arr2.sort()
时,arr2
数组对象将被排序。
然而,在比较对象时,数组的排序顺序并不重要。因为 arr1.sort()
和 arr1
指向内存中的同一个对象,所以第一个相等比较时返回 true
。对于第二个比较也是这样:arr2.sort()
和 arr2
指向内存中的同一个对象。
在第三个比较中,arr1.sort()
和 arr2.sort()
的排序顺序相同;但是,它们指向内存中的不同对象。因此,第三个测试结果为 false
。
2、Set 对象
const mySet = new Set([{ a: 1 }, { a: 1 }]);
const result = [...mySet];
console.log(result);
Answer: [{a: 1}, {a: 1}]
虽然 Set 对象确实会删除重复项,但我们使用的两个值是对内存中不同对象的引用,尽管它们具有相同的键值对。这与 {a:1}=={a:1}
为 false
的原因相同。
应该注意的是,如果集合是使用对象变量(比如 obj={a:1}
)创建的,那么新集合([obj,obj]
)将只有一个元素,因为数组中的两个元素引用内存中的同一个对象。
3、Object.freeze
const user = { name: 'Joe', age: 25, pet: { type: 'dog', name: 'Buttercup' } }; Object.freeze(user); user.pet.name = 'Daffodil'; console.log(user.pet.name);
Answer: Daffodil
Object.freeze 对象冻结将对对象执行浅冻结,但不会保护深层属性修改不受影响。在这个例子中,我们无法修改 user.age
,但我们可以修改 user.pet.name
. 如果我们觉得需要保护对象不被“修改,我们可以递归地使用对象冻结或者使用现有的“深度冻结”库。
4、Prototype
function Dog(name) { this.name = name; this.speak = function() { return 'woof'; }; } const dog = new Dog('Pogo'); Dog.prototype.speak = function() { return 'arf'; }; console.log(dog.speak());
Answer: woof
每次创建一个新的 Dog 实例时,我们都将该实例的 speak
属性设置为返回字符串 woof
的函数。因为每次我们创建一个新的 Dog 实例时都会设置这个属性,所以解释器永远不必在原型链上查找更远的内容来找到 speak
属性。
5、Promise.all
const timer = a => { return new Promise(res => setTimeout(() => { res(a); }, Math.random() * 100) ); }; const all = Promise.all([ timer('first'), timer('second') ]).then(data => console.log(data));
Answer: ["first", "second"]
我们可以可靠地以数组参数中提供它们的相同顺序返回。
6、Reduce
const arr = [ x => x * 1, x => x * 2, x => x * 3, x => x * 4 ]; console.log(arr.reduce((agg, el) => agg + el(agg), 1));
Answer: 120
对于Array#reduce,聚合的初始值(这里称为 agg
)在第二个参数中给出。在这种情况下,是1。然后,我们可以对函数进行迭代,如下所示:
1 + 1 * 1 = 2
2 + 2 * 2 = 6
6 + 6 * 3 = 24
24 + 24 * 4 = 120
7、扩展运算符
const arr1 = [{ firstName: 'James' }]; const arr2 = [...arr1]; arr2[0].firstName = 'Jonah'; console.log(arr1);
Answer: [{ firstName: "Jonah" }]
扩展运算符创建数组的浅拷贝,这意味着 arr2
中包含的对象仍指向 arr1
对象所指向的内存中的同一对象。因此,更改一个数组中对象的 firstName
属性也会被另一个数组中的对象所反映。
8、Array
const map = ['a', 'b', 'c'].map.bind([1, 2, 3]); map(el => console.log(el));
Answer: 1 2 3
['a','b','c'].map
调用时,this 指向的是['a', 'b', 'c']
,当通过 bind 方法修改 this 之后指向时变成了[1, 2, 3]
,所以代码可以改写成这种方式:
[1, 2, 3].map(el => console.log(el))
好了,今天的文章分享到这里,欢迎大家点赞留言和收藏。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论