当前位置: 首页 > 科技观察

只有10%的开发人员可以解决这些JavaScript挑战

时间:2023-03-21 01:36:11 科技观察

Ahead我们根据这些测验答案的统计数据发布了一篇包含最难主题的文章。为了确定这些主题,我们将所有已发布的测验按主题划分,共有15个主题,并计算每个主题的平均百分比。这个实验最有意思的是,除了统计正确答案,我们还调查了Javascript最难的地方,结果大相径庭。在调查中,大多数受访者最难回答的话题是Promises,据统计,Promises仅排在第4位。我们应该在每项任务旁边留下关于正确答案百分比的注释。您不应将此注释视为不变的和100%反映现实。首先,新程序员每天都会回答我们发布的测验和更改统计数据,文章中出现的所有数字都是在文章发布时确定的。其次,有些答案当然是不小心猜到了,或者点错了地方等等。然而,在采访了大量JS开发人员之后,我们可以自信地说这个统计数据清楚地反映了现实。那么,让我们看看TOP-5最难的JS挑战并分析一下,剧透:只有8%的受访者正确解决了TOP-1测验。Top-5,默认函数参数和函数长度属性,18%的人回答正确functionfoo(a,b=10,c){console.log(foo.length);}foo(1,2,3);这里的关键点是函数的length属性应该提供有关函数参数的信息,计算为她的正式定义的参数数量。默认参数特性是在ES2015中引入的。在此之前,所有函数参数都被视为形式参数,函数长度属性用于返回所有函数参数编号。随着默认参数的引入,长度属性的行为发生了变化。由于具有默认值的参数显然是可选的,因此此类参数不计入函数的长度。按照常识,默认值参数之后的所有参数也是可选的。因此,它们也不包含在函数的长度属性中。TOP-4,Object.defineProperty方法及其默认参数,14%的人回答正确我的公司);删除obj.myCompany;console.log(obj.myCompany);大多数受访者对该测验的回答是不确定的。原因:不确定Object.defineProperty()方法是如何工作的。Object.defineProperty()方法定义对象的新属性,或修改对象的现有属性。语法:Object.defineProperty(obj,prop,descriptors)请参见此处:obj—定义或修改属性的对象。prop—要定义或修改的属性的名称。描述符——属性的描述符。有两种类型的描述符:数据描述符(值、可写、可枚举、可配置)和访问描述符(获取和设置)。在此示例的上下文中,我们对数据描述符感兴趣。默认情况下,使用Object.defineProperty()添加的属性不可写、不可枚举和不可配置。可配置属性指定是否可以从对象中删除该属性,以及将来是否可以更改属性描述符。如果为true,则该属性将可用于删除和修改其描述符,如果为false,则无法修改。默认设置为假。因此,测验的正确答案是intspirit,删除此属性的尝试将被忽略。如果你在严格模式下运行代码,你会得到一个错误:TypeError:Cannotdeleteproperty'myCompany'of#Top-3,Array.map&parseInt,14%的人回答正确constnumbers=['9','10','11'].map(parseInt);console.log(numbers);Array.map()方法接受带有3个参数的回调函数。我们只对前两个感兴趣:值和索引。parseInt函数有两个参数:一个要转换为数字的字符串和一个基数。因此,在我们的示例中,将使用以下参数调用parseInt:parseInt('9',0);parseInt('10',1);parseInt('11',2);要了解parseInt是如何处理这些基数的,我们先看一下mdn中的radix参数说明:radix—一个介于2和36之间的整数,代表字符串的基数(数学数系中的基数)。如果超出此范围,该函数将始终返回NaN。如果为0或未提供,则JavaScript假定以下内容:1)。如果输入字符串以0x或0X(零后跟小写或大写X)开头,则删除前导空格和可能的+/-符号,假定以16为底,字符串的其余部分将被解析为十六进制数。2).如果输入字符串以任何其他值开头,则基数为10(十进制)。根据这个定义,我们得到以下内容:parseInt('9',0)->radix0等同于没有基数的调用。由于第一个参数不是以0x或0X开头,因此基数将默认为10->parseInt('9',10)->9parseInt('10',1)->1—基数无效(超出范围)->NaNparseInt('11',2)->2—有效基数,二进制中的11是3->3TOP-2,使用Object.create和Object.assign克隆对象。11%的人回答正确functionUser(){this.verified=true;}constuser=newUser();constadmin=Object.create(user);constclone1={...admin};constclone2=Object.assign({},admin);console.log(admin.verified,clone1.verified,clone2.verified);我们的频道中有一系列测验,专门针对Object.assign和...spread运算符之间的工作差异。对于任何对深度JS感兴趣的人,我们强烈建议解决所有这些问题。在每个测验下,您会找到有关其工作原理的详细说明。这只是对该示例中代码工作原理的简要说明,因为它被证明是整个测验系列中对受访者来说最难的。所以..让我们了解这个例子中发生了什么。1).已验证属性设置为true的用户构造函数及其实例已创建:functionUser(){this.verified=true;}constuser=newUser();2).以用户对象为原型创建管理对象。根据mdn网站的介绍:Object.create()方法创建一个新的对象,使用已有的对象作为新创建对象的原型。constadmin=Object.create(user);3).创建了两个克隆:一个使用...spread运算符,另一个使用Object.assign:constclone1={...admin};常量克隆2=对象。分配({},管理员);你知道rest和spread运算符的区别吗?两者都使用三个点(...),但两个运算符并不相同。它们之间的主要区别在于,rest运算符的目标是将一些剩余的提供值放入数组中,而spread运算符将iterable扩展为单个元素。4).检查验证的属性是否被克隆:console.log(admin.verified,clone1.verified,clone2.verified);//true,undefined,undefinedadmin对象显然将其verified属性设置为true,因为它使用user作为其原型。但是,如您所见,所有克隆都没有经过验证的属性。这是因为...spread运算符和Object.assign在克隆时都忽略了原型。这些对象的原型:admin.__proto__User{verified:true},clone1.__proto__[Object:nullprototype]{},clone2.__proto__[Object:nullprototype]{}克隆一个对象,包括它的原型:constclone1={__proto__:Object.getPrototypeOf(obj),...obj};constclone2=Object.assign(Object.create(Object.getPrototypeOf(obj)),obj);注意:__proto__只是浏览器中的一个强制特性,在一般的JS引擎中是不可用的。TOP-1,字符串函数和instanceof操作符,8%的人答对了varstr='Hello';varstr2=String('Hello');console.log(strinstanceofString);console.log(str2instanceofString);这是一百多个特别挑选的非平凡任务中难度最大的一个。只有2个正确答案-其中一个是频道管理员给出的,呵呵:)有什么问题吗?如果查看答案的统计数据,您会发现受访者的意见大致介于两个错误答案之间。在发布时-38%的开发人员认为两个表达式都会返回true,而35%的开发人员认为只有第二个语句是true。下半场比分更接近。可以假设那些回答表达式'Hello'instanceofString为假且String('Hello')instanceofString为真,知道instanceof运算符只作用于对象,而不是基元,而是作用于函数返回的String内容是使困惑。事实上,这两种说法都是错误的。因为:instanceof运算符仅适用于对象。字符串文字“Hello”是原始的。非构造函数上下文中的字符串调用(不使用new关键字的调用)返回原始字符串。到目前为止,我已经分解了这5个问题,希望对您有用。综上所述,关于JavaScript其实有很多具有挑战性的学习试题。我只是选择了一些看起来容易混淆和容易出错的问题。我希望你能从他们身上学到新东西。