解析10个JavaScript笔试题

开发 前端
作为JavaScript开发人员,我们可以挑战自己成长的一个方法就是用刷题来练习!下面的问题旨在具有挑战性和启发性。如果你确切地知道如何回答每一个问题,那很好,但如果你答错了,并知道为什么答错了,我认为那就更好了!

 作为JavaScript开发人员,我们可以挑战自己成长的一个方法就是用刷题来练习!下面的问题旨在具有挑战性和启发性。如果你确切地知道如何回答每一个问题,那很好,但如果你答错了,并知道为什么答错了,我认为那就更好了!

问题1:数组排序比较

考虑以下数组。在不同的排序条件中会输出什么?

 

  1. const arr1 = ['a''b''c']; 
  2. const arr2 = ['b''c''a']; 
  3.  
  4. console.log( 
  5.   arr1.sort() === arr1, 
  6.   arr2.sort() == arr2, 
  7.   arr1.sort() === arr2.sort() 
  8. ); 

答案: true, true, false

这里有几个概念在起作用。首先,数组 sort 方法对原始数组进行排序,并返回对该数组的引用。这意味着在编写 arr2.sort() 时,将对 arr2 数组对象进行排序。

事实证明,在比较对象时,数组的排序顺序并不重要。由于 arr1.sort() 和 arr1 指向内存中的同一对象,因此第一个相等测试返回 true。第二个比较也是如此:arr2.sort() 和 arr2 指向内存中的同一对象。

在第三个测试中,arr1.sort() 和 arr2.sort() 的排序顺序相同;但是,它们指向内存中的不同对象。因此,第三项测试的结果为 false。

问题2:set 一组对象

考虑下面的对象 Set 集合,它们散布到一个新的数组中。会输出什么?

 

  1. const mySet = new Set([{ a: 1 }, { a: 1 }]); 
  2.  
  3. const result = [...mySet]; 
  4.  
  5. console.log(result); 

答案:[{a: 1}, {a: 1}]。

尽管 Set 对象确实会删除重复项,但是尽管具有相同的键值对,但我们使用 Set 创建的两个值是对内存中不同对象的引用。这与 {a:1} === {a:1} 为 false 的原因相同。

应该注意的是,如果集合是使用对象变量创建的,例如 obj = {a:1},则 new Set([obj,obj]) 将只有一个元素,因为数组中的两个元素都引用内存中的同一对象。

问题3:深度对象可变性

考虑下面这个代表用户Joe和他的狗Buttercup的对象。我们使用 Object.freeze 保存我们的对象,然后尝试更改Buttercup的名称。会输出什么?

 

  1. const user = { 
  2.   name'Joe'
  3.   age: 25, 
  4.   pet: { 
  5.     type: 'dog'
  6.     name'Buttercup' 
  7.   } 
  8. }; 
  9.  
  10. Object.freeze(user); 
  11.  
  12. user.pet.name = 'Daffodil'
  13.  
  14. console.log(user.pet.name); 

答案:Daffodil。

Object.freeze 将对对象执行浅层冻结,但不会保护深层属性不被突变。在此示例中,我们将无法更改user.age,但对 user.pet.name 进行更改不会有问题。如果我们认为需要保护某个对象以免其被“彻底破坏”,则可以递归应用 Object.freeze 或使用现有的“deep freeze”库。

问题4:原型继承

在这个问题中,我们有一个 Dog 构造函数,我们的 dog 显然知道说话的命令。当我们要求Pogo讲话时,以下示例中将会输出什么?

 

  1. function Dog(name) { 
  2.   this.name = name
  3.   this.speak = function() { 
  4.     return 'woof'
  5.   }; 
  6.  
  7. const dog = new Dog('Pogo'); 
  8.  
  9. Dog.prototype.speak = function() { 
  10.   return 'arf'
  11. }; 
  12.  
  13. console.log(dog.speak()); 

答案:woof。

每次创建一个新的 Dog 实例时,我们都会将该实例的 speak 属性设置为一个返回字符串 woof 的函数。由于每次创建新的 Dog 实例时都会设置该字段,因此解释器无需再向上寻找原型链来查找 speak 属性。结果,永远不会使用 Dog.prototype.speak 上的 speak 方法。

问题5:Promise.all Resolve Order

在这个问题中,我们有一个 timer 函数,该函数返回一个 Promise,该Promise将在随机时间后解析。我们使用 Promise.all 解析 timers 数组。会输出什么,还是随机的?

 

  1. const timer = a => { 
  2.   return new Promise(res => 
  3.     setTimeout(() => { 
  4.       res(a); 
  5.     }, Math.random() * 100) 
  6.   ); 
  7. }; 
  8.  
  9. const all = Promise.all([ 
  10.   timer('first'), 
  11.   timer('second'
  12. ]).then(data => console.log(data)); 

答案: ["first", "second"]。

Promise解决的顺序与 Promise.all 无关。我们可以可靠地指望它们以数组参数中提供的相同顺序返回。

问题6:Reduce Math

下面的代码输出什么?

 

  1. const arr = [ 
  2.   x => x * 1, 
  3.   x => x * 2, 
  4.   x => x * 3, 
  5.   x => x * 4 
  6. ]; 
  7.  
  8. console.log(arr.reduce((agg, el) => agg + el(agg), 1)); 

答案:120。

使用 Array#reduce 时,聚合器的初始值(在这里称为 agg)在第二个参数中给出。在这种情况下,就是 1。然后,我们可以如下迭代函数:

  • 1 +1 * 1 = 2(下一次迭代中聚合器的值)
  • 2 + 2 * 2 = 6(下一次迭代中聚合器的值)
  • 6 + 6 * 3 = 24(下一次迭代中聚合器的值)
  • 24 + 24 * 4 = 120(最终值)

因此,它是120!

问题7:短路通知

让我们向用户显示一些通知!以下代码段会输出什么?

 

  1. const notifications = 1; 
  2.  
  3. console.log( 
  4.   `You have ${notifications} notification${notifications !== 
  5.     1 && 's'}` 
  6. ); 

答案:“You have 1 notificationfalse”。

不幸的是,我们的短路评估将无法按此处的预期进行:notifications!== 1 && 's' 评估为 false,这意味着我们实际上将输出 You have 1 notificationfalse。如果我们希望代码段正常工作,则可以考虑条件运算符:${notifications === 1 ? '' : 's'}。

问题8:Spread并重命名

考虑以下具有单个对象的数组。当我们扩展该数组并更改0索引对象上的 firstName 属性时会发生什么?

 

  1. const arr1 = [{ firstName: 'James' }]; 
  2. const arr2 = [...arr1]; 
  3. arr2[0].firstName = 'Jonah'
  4.  
  5. console.log(arr1); 

答案:[{ firstName: "Jonah" }]。

Spread创建一个数组的浅层副本,这意味着 arr2 中包含的对象仍指向 arr1 对象指向的内存中的同一对象。因此,在一个数组中更改对象的 firstName 属性将通过另一个数组中的对象更改而反映出来。

问题9:数组方法绑定

在以下情况下会输出什么?

 

  1. const map = ['a''b''c'].map.bind([1, 2, 3]); 
  2. map(el => console.log(el)); 

答案:1 2 3。

['a', 'b', 'c'].map,当调用时,将调用 Array.prototype.map,其 this 值为 ['a', 'b', 'c']。但是,当作为引用使用时,['a', 'b', 'c'].map 只是对 Array.prototype.map 的引用,而不是调用。

Function.prototype.bind 将把函数的 this 绑定到第一个参数(在本例中是 [1, 2, 3]),用这样的this 调用 Array.prototype.map 会导致这些项被迭代并记录下来。

问题10:Set 唯一性和顺序

在以下问题中,我们使用 Set 对象和spread语法创建一个新数组。输出的内容(考虑:项目被强制为唯一的吗?它们是否已排序?)

 

  1. const arr = [...new Set([3, 1, 2, 3, 4])]; 
  2. console.log(arr.length, arr[2]); 

答案:4 2。

Set 对象将强制唯一元素(集合中已经存在的重复元素将被忽略),但不会更改顺序。所得的 arr 数组将为[3,1,2,4],表示 arr.length 为 4 ,而 arr [2] (数组的第三个元素)为 2。

责任编辑:华轩 来源: 今日头条
相关推荐

2011-08-11 17:39:25

Objective-C笔试题

2017-07-27 15:05:18

前端JavaScript难点

2015-03-26 10:17:31

javascriptjavascript笔

2015-04-07 14:05:13

前端阿里在线笔试题

2009-06-15 17:18:25

Java笔试题

2023-08-02 18:44:47

JavaScript命名web

2018-04-04 09:35:01

前端JavaScript面试题

2010-08-11 11:32:57

谷歌笔试题谷歌笔试题

2010-08-11 11:57:02

微软笔试题微软笔试题

2010-08-11 11:22:00

IBM笔试题IBM笔试

2010-08-11 12:07:08

腾讯笔试题腾讯笔试题

2009-07-28 13:35:18

2010-08-16 15:27:22

雅虎笔试题

2010-08-18 10:17:00

2021-03-15 08:13:19

JavaScript开发代码

2011-06-30 16:10:01

JavaScript

2019-11-13 09:01:48

开源JavaScript模板引擎

2017-12-05 11:25:09

2015-08-27 09:27:34

JavaScript面试题

2019-08-13 08:43:07

JavaScript前端面试题
点赞
收藏

51CTO技术栈公众号