🏆 学习 JS,从忍者到杀手
相信大家对《JS 忍者秘籍》一定非常熟悉。想要成为忍者,必须自宫对原型、闭包、函数、作用域等概念极其熟悉,对各种语言核心概念倒背如流。如果你有幸能将这些原理应用到实战,创建各种精巧的原型,并通过社区的考验,那才能获得忍者勋章。
不过,杀手和忍者不同,杀手天生就追求每一个细节。确切的说,JS 杀手追求回归 JS 语言本身(而不是编程实践)。
以下,我准备了一些 JS 难题,它们和某些 JS 核心概念相关。每一个 JS 杀手,或者想成为 JS 杀手的开发都可以来试试,看看自己对 JS 的掌握程度。如果回答不出来的话也请不要气馁,因为其中涉及的内容和日常编程实践相差甚远。
前置说明:
- 代码执行以 ES6 语言规范为标准。
- 每一个代码片段都以全局代码的形式运行。
- 每一个题目都互相独立,其变量互不干涉。
准备好了吗?杀手试炼开始了!
1.通常,杀手在出门前会先做个热身运动~
do = {
get exercise() {
delete do.exercise
return do.exercise
}
}
do.exercise
2.出门前别忘了检查一下防弹衣和弹药~
;[Number.isNaN('AK(AK-103)'), isNaN('Bullet(7.62 x 39mm BP)')]
3.插上钥匙,打开车门~
;(function(where, undefined, where) {
console.log(arguments[1] + where)
})('L', 'sun', 'R')
;('use strict')
;(function(where, undefined, where) {
console.log(arguments[1] + where)
})('L', 'sun', 'R')
4.正在加速,坐稳了!
;(function(x = 1, undefined, y = 2) {
return [...arguments].reduce((speed, acceleration) => speed + acceleration, 0)
})()
5.一边开车,一边寻找目标~
;[
function() {}.__proto__ === Function.prototype,
Function.prototype === Object.prototype,
Function.__proto__ === Object.__proto__,
Function.prototype.__proto__ === Object.prototype
].filter(Boolean).length
6.终于找到目标了!
var target = {
seen() {
console.log(this === target)
}
}
;('haha', target.seen)()
7.破坏警铃~
/* 注意:浏览器环境,两块代码分开执行,防止变量提升 */
// 先执行这三行(破坏左边的警铃)
var alert = (...args) => console.log(args)
delete alert
console.log(typeof window.alert)
// 再执行这三行(破坏右边的警铃)
var alert = (...args) => console.log(args)
delete alert
console.log(typeof window.alert)
8.计算距离,瞄准目标!
var killer = (target = {
y: 2,
z: 3
})
target.x = target = 1
console.log(killer.x < killer.y < killer.z)
console.log(target.x < target.y < target.z)
9.BANG!
;[
void "killer's target" === typeof down,
delete void "killer's target" === delete undefined,
delete undefined === delete null
].filter(Boolean).length
10.“邪恶”的情绪在内心滋生!
// 附:heart 和 ghost 是从未定义过的变量
eval(`typeof typeof ghost === typeof ${typeof heart}`)
11.前行路上,心魔又一次袭来 😈,它会淹没你吗?
var heart = 'alive'
;(function evalAttack() {
var eval = window.eval
var ghost = window.eval
var heart = 'dead'
eval('console.log(heart)')
;(0, eval)('console.log(heart)')
ghost('console.log(heart)')
})()
12.SAN 值(理智)狂减!
// finally 中的 console.log 会输出么?
// return 语句会返回么?
;(function() {
let san = 3
try {
--san
return san
} finally {
--san
console.log(san)
}
})()
13.来做道数学题吧,恢复一下理智~
;[
// killer have to be careful
0.1 + 0.2 === 0.3,
Number.MAX_SAFE_INTEGER === Number.MAX_SAFE_INTEGER + 1,
Number.MAX_VALUE === Number.MAX_VALUE + 1
].filter(Boolean).length
14.把“行李”搬到后备箱,回家!
drivetime = 0
isArived = false
console.log('go')
setTimeout(() => (isArived = true), 0)
while (++drivetime && !isArived) {}
console.log('home')
15.开车时需要避开路上的井盖!
;[
// DEX + 100!
+0 === -0,
String(+0) === String(-0),
+0 * 'hole' === -0 * 'hole',
1 / +0 === 1 / -0
].filter(Boolean).length
阅读更多
Hi,还好吗,多喝热水感觉如何?有没有喜欢上这种风格别具一格的挑战呢?
虽然说试炼中的每道题背后的语言细节可能只是规范中一个段落,一句话,甚至一行标准所描述的内容,和编程实践几乎毫不相干,但实际上我只是想引起你对语言规范的兴趣。语言规范十分有意思,学习规范也可以帮助你更深入理解这门语言,理解引擎的工作机理、AST 的具体表现以及各类框架代码中的黑科技,而不仅仅只是成为语言本身的使用者。 共勉。
如果你仍意犹未尽,可以继续试试这些难题(内内,别忘了先给我点赞投币关注三连呐):