这是我目前为止见到的一些比较罕见且奇怪的js面试题。 与正常的js面试题不同,这些题看似简单,但是却考察了你对js理解的透彻程度。你能答出几道呢?
第一题
x 为什么值时打印 Hello?
const x = ____;
if(x !== x) {
console.log('Hello');
}
解答
NaN
这题似乎是老生常谈,NaN 不等于任何值,甚至不等于自身
如果要判断一个值是否为 NaN,可以使用 Number.isNaN(x) 或者 Object.is(x, NaN)。
第二题
x 为什么值时打印 Hello?
const x = ____;
if(x === x + 1) {
console.log('Hello');
}
解答
Infinity
本题答案不唯一,任何大于 Number.MAX_SAFE_INTEGER 的值都有可能产生此效果。
第三题
x 为什么值时打印 Hello?
const x = ____;
if((x + 1 !== 1) && (x + 2 === 2)) {
console.log('Hello');
}
解答
Number.EPSILON
Number.EPSILON属性表示1与Number可表示的大于1的最小的浮点数之间的差值。
这么说可能有点难以理解,Number.EPSILON 是 ES6 新加的一个属性,用于解决浮点数精度问题,比如著名的
0.1 + 0.2 !== 0.3
这时候只需要
Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON; // true
Number.EPSILON 可以用来规定浮点数 能够接受的误差范围,如果两个浮点数差的绝对值小于 Number.EPSILON,我们就可以假定这两个浮点数是相等的。
因为 2 精度超过了 1, 所以 Number.EPSILON 在计算中精度丢失了,也是 2 + Number.EPSILON === 2的原因。
第四题
x 为什么值时打印 Hello?
const x = ____;
if(x > x) {
console.log('Hello');
}
解答
const x = {
value: 0,
[Symbol.toPrimitive]() {
return --this.value;
}
}
本题看上去不太可能,一个值不可能大于自身。
但是js在做数学运算时(比如加减乘除、大小比较)时,如果对象并非 Number 等值类型,js会尝试调用 [Symbol.toPrimitive] 获取它的值类型。
这里我们就可以钻空子,让 x 为一个 object,然后利用它作数学运算的副作用(Side Effects) [Symbol.toPrimitive]时将其每次返回的值递减,这样便造成了 x > x 为 true。
本题的解法也可以解答出第三题。
第五题
x 为什么值时打印 Hello?
if(!isNaN(x) && x !== x) {
console.log('Hello');
}
解答
Object.defineProperty(globalThis, 'x', {
get() {
return Math.random();
}
})
这题似乎是第一题的进化版,但是排除了 x 是 NaN 的可能性,而 x 也必须是 Number 或者可以转成Number的值。并且也没有进行数学运算,所以想要利用 [Symbol.toPrimitive] 、 toString() 、 valueOf() 等副作用方法似乎也不可能。
难道除了 NaN ,还有什么值不等于自身吗?
我们考虑到,x 并没有使用声明方式定义,所以我们完全可以把 x 定义为全局对象的属性。当获取 x 时,相当于隐式调用了 globalThis.x。这边给了我们可乘之机,我们将 x 的 get() 方法每次都返回一个随机值,这样可以保证几乎在任何情况下每次获取到的 x 值都不一样。
第六题
x 为什么值时打印 Hello?
const x = ____;
if(typeof x === 'undefined' && x.length > 0) {
console.log('Hello');
}
解答
const x = document.all;
什么鬼?如果 x 的类型是 undefined, x 就一定是 undefined 啊,引用 x.length 按照常理肯定会抛出异常不是吗?
难道 typeof 还能被重载?
这里算是js历史遗留的一个后门,document.all 最初是由IE浏览器拥有的,并不属于 W3C 规范范畴,他返回包括 html 自身在内的所有DOM集合。
ECMA规定 document.all 对象拥有内部槽 [[IsHTMLDDA]] , 拥有该槽的对象 boolean 值为 false、并且 typeof 返回 undefined。