wtfjs:一个接近20k关注的有趣JS项目(下),前端中常见的面试题

文章探讨了JavaScript中的类定义、匿名类、非强制对象类型、箭头函数特性、构造器限制、自动分号插入、对象链式赋值、数组和对象操作、关系运算符的行为以及浮点数toFixed的细微差异。同时提到了前端开发者的学习资源分享。
摘要由CSDN通过智能技术生成

const foo = {

class: function() {}

};

还有 ES6 标准速记方法定义。此外,类可能是匿名的。因此,如果我们放弃 : function 部分,我们将得到:

class {

class() {}

}

默认类的结果总是一个简单的对象。其类型应返回 'object' 。

在这里阅读更多

  • 14.3 Method Definitions

  • 14.5 Class Definitions

非强制对象


有着名的符号,有一种方法可以摆脱类型的强制。看一看:

function nonCoercible(val) {

if (val == null) {

throw TypeError(“nonCoercible should not be called with null or undefined”);

}

const res = Object(val);

res[Symbol.toPrimitive] = () => {

throw TypeError(“Trying to coerce non-coercible object”);

};

return res;

}

现在我们可以这样使用:

// objects

const foo = nonCoercible({ foo: “foo” });

foo * 10; // -> TypeError: Trying to coerce non-coercible object

foo + “evil”; // -> TypeError: Trying to coerce non-coercible object

// strings

const bar = nonCoercible(“bar”);

bar + “1”; // -> TypeError: Trying to coerce non-coercible object

bar.toString() + 1; // -> bar1

bar === “bar”; // -> false

bar.toString() === “bar”; // -> true

bar == “bar”; // -> TypeError: Trying to coerce non-coercible object

// numbers

const baz = nonCoercible(1);

baz == 1; // -> TypeError: Trying to coerce non-coercible object

baz === 1; // -> false

baz.valueOf() === 1; // -> true

??? 说明:

  • A gist by Sergey Rubanov

  • 6.1.5.1 Well-Known Symbols

棘手的箭头功能


考虑下面的例子:

let f = () => 10;

f(); // -> 10

好吧,但是这是怎么说的呢?

let f = () => {};

f(); // -> undefined

??? 说明:

你可能期待 {} 而不是 undefined。这是因为花括号是箭头函数语法的一部分,所以 f 会返回未定义的。然而要从箭头函数直接返回 {} 对象也是可能的,要通过用括号把返回值括起来。

箭头函数不能作为构造器


考虑下面的例子:

let f = function() {

this.a = 1;

};

new f(); // -> { ‘a’: 1 }

现在,试着用箭头函数做同样的事情:

let f = () => {

this.a = 1;

};

new f(); // -> TypeError: f is not a constructor

??? 说明:

箭头函数不能作为构造器并且会在被 new 时抛出错误。因为它有一个词域的 this,而且也没有 prototype 属性,所以这样做没什么意义。

arguments 和箭头函数


考虑下面的例子:

let f = function() {

return arguments;

};

f(“a”); // -> { ‘0’: ‘a’ }

现在,试着用箭头函数做同样的事情:

let f = () => arguments;

f(“a”); // -> Uncaught ReferenceError: arguments is not defined

??? 说明:

箭头函数是注重短小和词域下的 this 的常规函数的轻量级版本。同时箭头函数不提供 arguments 对象的绑定。作为一个有效的替代选择使用 rest parameters 来得到同样的结果:

let f = (…args) => args;

f(“a”);

  • Arrow functions at MDN.

棘手的返回


return 语句是很棘手的. 看下面的代码:

(function() {

return

{

b: 10;

}

})(); // -> undefined

??? 说明:

return 和返回的表达式必须在同一行:

(function() {

return {

b: 10

};

})(); // -> { b: 10 }

这是因为一个叫自动插入分号的概念,它会在大部分换行处插入分号。第一个例子里,有一个分号被插入到 return 语句和对象字面量中间。所以函数返回 undefined 而对象字面量不会被求值。

  • 11.9.1 Rules of Automatic Semicolon Insertion

  • 13.10 The return Statement

对象的链式赋值


var foo = { n: 1 };

var bar = foo;

foo.x = foo = { n: 2 };

foo.x; // -> undefined

foo; // -> {n: 2}

bar; // -> {n: 1, x: {n: 2}}

从右到左,{n: 2} 被赋值给 foo,而此赋值的结果 {n: 2} 被赋值给 foo.x,因此 bar 是 {n: 1, x: {n: 2}} 因为 bar 是 foo 的一个引用。但为什么 foo.x 是 undefined 而 bar.x 不是呢?

??? 说明:

foo 和 bar 引用同一个对象 {n: 1},而左值在赋值前解析。foo = {n: 2} 是创建一个新对象,所以 foo 被更新为引用那个新的对象。这里的戏法是 foo.x = ... 中的 foo 作为左值在赋值前就被解析并依然引用旧的 foo = {n: 1} 对象并为其添加了 x 值。在那个链式赋值之后,bar 依然引用旧的 foo 对象,但 foo 引用新的没有 x 的 {n: 2} 对象。

它等价于:

var foo = { n: 1 };

var bar = foo;

foo = { n: 2 }; // -> {n: 2}

bar.x = foo; // -> {n: 1, x: {n: 2}}

// bar.x 指向新的 foo 对象的地址

// 这不等价于:bar.x = {n: 2}

使用数组访问对象属性


var obj = { property: 1 };

var array = [“property”];

obj[array]; // -> 1

那关于伪多维数组创建对象呢?

var map = {};

var x = 1;

var y = 2;

var z = 3;

map[[x, y, z]] = true;

map[[x + 10, y, z]] = true;

map[“1,2,3”]; // -> true

map[“11,2,3”]; // -> true

??? 说明:

括号操作符将传递给字符串的表达式转换为字符串。将一个元素数组转换为字符串,就像将元素转换为字符串:

[“property”].toString(); // -> ‘property’`

Null 和关系运算符


null > 0; // false

null == 0; // false

null >= 0; // true

??? 说明:

长话短说,如果 null 小于 0 是 false,那么 null >= 0 则是 true。请阅读这里的详细解释。

Number.toFixed()显示不同的数字


Number.toFixed() 在不同的浏览器中会表现得有点奇怪。看看这个例子:

(0.7875).toFixed(3);

// Firefox: -> 0.787

// Chrome: -> 0.787

// IE11: -> 0.788

(0.7876).toFixed(3);

// Firefox: -> 0.788

// Chrome: -> 0.788

// IE11: -> 0.788

??? 说明:

尽管你的第一直觉可能是 IE11 是正确的而 Firefox/Chrome 错了,事实是 Firefox/Chrome 更直接地遵循数字运算的标准(IEEE-754 Floating Point),而 IE11 经常违反它们(可能)去努力得出更清晰的结果。

你可以通过一些快速的测试来了解为什么它们发生:

// 确认 5 向下取证的奇怪结果

(0.7875).toFixed(3); // -> 0.787

// 当你展开到 64 位(双精度)浮点数准确度限制时看起来就是一个 5

(0.7875).toFixed(14); // -> 0.78750000000000

// 但如果你超越这个限制呢?

(0.7875).toFixed(20); // -> 0.78749999999999997780

浮点数在计算机内部不是以一系列十进制数字的形式存储的,而是通过一个可以产生一点点通常会被 toString 或者其他调用取整的不准确性的更复杂的方法,但它实际上在内部会被表示。

在这里,那个结尾的 “5” 实际上是一个极其小的略小于 5 的分数。将其以任何常理的长度取整它都会被看作一个 5,但它在内部通常不是 5。

IE11,尽管如此,描述这个数字时只是加上一些 0,甚至在 toFixed(20) 的时候也是这样,因为它看起来强制取整了值来减少硬件限制带来的问题。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

。将其以任何常理的长度取整它都会被看作一个 5,但它在内部通常不是 5。

IE11,尽管如此,描述这个数字时只是加上一些 0,甚至在 toFixed(20) 的时候也是这样,因为它看起来强制取整了值来减少硬件限制带来的问题。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-cvaGnGQW-1710899473980)]
[外链图片转存中…(img-Z4EQ2eFb-1710899473981)]
[外链图片转存中…(img-5zYFt0t9-1710899473981)]
[外链图片转存中…(img-PySX49I4-1710899473982)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-Y4925K8H-1710899473982)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值