作为JavaScript开发者,挑战自我成长的一种方式就是刷题练习!下面的问题旨在具有挑战性和指导性。如果您确切地知道如何回答每个问题,那很好,但是如果您答错了并且知道为什么,我认为那就更好了!问题一:数组排序比较考虑以下数组。在不同的排序条件下会输出什么?constarr1=['a','b','c'];constarr2=['b','c','a'];console.log(arr1.sort()===arr1,arr2.sort()==arr2,arr1.sort()===arr2.sort());答案:真、真、假这里有几个概念在起作用。首先,数组排序方法对原始数组进行排序并返回对该数组的引用。这意味着当写arr2.sort()时,arr2数组对象将被排序。事实证明,在比较对象时,数组的排序顺序并不重要。由于arr1.sort()和arr1指向内存中的同一个对象,所以第一个相等性测试返回true。第二次比较也是如此:arr2.sort()和arr2指向内存中的同一个对象。在第三个测试中,arr1.sort()和arr2.sort()具有相同的排序顺序;但是,它们指向内存中的不同对象。因此,第三次测试的结果是假的。问题2:设置一组对象考虑以下Set对象集合,它们被分散到一个新数组中。会输出什么?constmySet=newSet([{a:1},{a:1}]);constresult=[...mySet];控制台日志(结果);答案:[{a:1},{a:1}]。虽然Set对象确实去除了重复项,但是我们用Set创建的两个值尽管有相同的键值对,但它们是对内存中不同对象的引用。这与{a:1}==={a:1}为假的原因相同。应该注意的是,如果集合是使用对象变量创建的,例如obj={a:1},那么newSet([obj,obj])将只有一个元素,因为数组中的两个元素都引用内存中的同一个对象。问题3:深层对象可变性考虑以下代表用户Joe和他的狗Buttercup的对象。我们用Object.freeze保存我们的对象,然后尝试更改Buttercup的名称。输出什么?constuser={name:'Joe',age:25,pet:{type:'dog',name:'Buttercup'}};Object.freeze(user);user.pet.name='Daffodil';console.log(user.pet.name);答案:水仙花。Object.freeze将对对象执行浅层冻结,但不会保护深层属性免于突变。在本例中,我们无法更改user.age,但可以更改user.pet.name。如果我们认为我们需要保护一个对象不被“彻底摧毁”,我们可以递归地应用Object.freeze或使用现有的“深度冻结”库。问题4:原型继承在这个问题中,我们有一个Dog构造函数,我们的狗显然知道要说的命令。下面这个例子,当我们让Pogo说话时,会输出什么?functionDog(name){this.name=name;this.speak=function(){return'woof';};}constdog=newDog('Pogo');Dog.prototype.speak=function(){return'arf';};console.log(dog.speak());答案:汪。每次我们创建一个新的Dog实例时,我们都会将该实例的speak属性设置为一个返回字符串woof的函数。由于每次创建新的Dog实例时都会设置此字段,因此解释器不再需要查找原型链来查找speak属性。因此,永远不会使用Dog.prototype.speak上的speak方法。问题5:Promise.allResolveOrder在这个问题中,我们有一个计时器函数,它返回一个承诺,该承诺将在随机时间后解决。我们使用Promise.all来解析定时器数组。会输出什么,还是random?consttimer=a=>{returnnewPromise(res=>setTimeout(()=>{res(a);},Math.random()*100));};constall=Promise.all([计时器('第一'),计时器('第二')]).then(data=>console.log(data));答案:[“第一”,“第二”]。Promise解析的顺序与Promise.all无关。我们可以可靠地指望它们以数组参数中提供的相同顺序返回。问题6:下面ReduceMath代码的输出是什么?constarr=[x=>x*1,x=>x*2,x=>x*3,x=>x*4];console.log(arr.reduce((agg,el)=>agg+el(聚合),1));答案:120.使用Array#reduce时,聚合器(此处称为agg)的初始值在第二个参数中给出。在这种情况下,1.然后我们可以按如下方式迭代函数:1+1*1=2(下一次迭代中聚合器的值)2+2*2=6(下一次迭代中聚合器的值)6+6*3=24(聚合器在下一次迭代中的值)24+24*4=120(最终值)所以,是120!问题7:短路通知让我们向用户显示一些通知!下面的代码片段会输出什么?constnotifications=1;console.log(`你有${notifications}notification${notifications!==1&&'s'}`);回答:“你有1个通知是假的”。不幸的是,我们的短路评估在这里不会像预期的那样工作:notifications!==1&&'s'评估为false,这意味着我们实际上会输出Youhave1notificationfalse。如果我们想让代码片段工作,我们可以考虑条件运算符:${notifications===1?'':'s'}。问题8:传播和重命名考虑以下具有单个对象的数组。当我们扩展该数组并更改索引为0的对象的firstName属性时会发生什么?constarr1=[{firstName:'James'}];constarr2=[...arr1];arr2[0].firstName='Jonah';console.log(arr1);答案:[{firstName:"Jonah"}]。Spread创建数组的浅表副本,这意味着arr2中包含的对象仍然指向arr1对象所指向的内存中的相同对象。因此,更改一个数组中对象的firstName属性将反映在另一个数组中对象的更改中。问题九:当?constmap=['a','b','c'].map.bind([1,2,3]);map(el=>console.log(el));答案:123.['a','b','c'].map在被调用时,将调用Array.prototype.map并使用['a','b','c']的值。但是,当用作引用时,['a','b','c'].map只是对Array.prototype.map的引用,而不是调用。Function.prototype.bind会将函数的this绑定到第一个参数(在本例中为[1,2,3]),并使用这样的this调用Array.prototype.map将导致项目被迭代并记录下来。问题10:设置唯一性和顺序在下面的问题中,我们使用Setobject和spread语法创建一个新数组。什么是输出(考虑:是否强制项目是唯一的?它们是否排序?)constarr=[...newSet([3,1,2,3,4])];console.log(arr.length,arr[2]);答案:42.Set对象将强制使用唯一元素(集合中已有的重复元素将被忽略),但不会更改顺序。生成的arr数组将为[3,1,2,4],这意味着arr.length为4,arr[2](数组的第三个元素)为2。
