I believe we are very familiar with “JS Ninja Book”. To be a ninja, you must be familiar with the concepts of archetypes, closures, functions, scopes, etc., and have memorized the core concepts of various languages. If you’re lucky enough to put these principles into action, create elaborate prototypes, and pass the community test, you’ll earn a Ninja medal.

Unlike ninjas, however, killers are born to pursue every detail. Specifically, JS killers pursue a return to the JS language itself (rather than programming practices).

Below, I’ve prepared some JS puzzles that relate to some of the core JS concepts. Every JS killer, or want to become JS killer development can try to see their grasp of JS. Don’t be discouraged if you can’t answer the question, because it’s a far cry from everyday programming practice.

Pre-instructions:

  • Code execution is based on the ES6 language specification.
  • Each snippet runs as global code.
  • Each subject is independent and its variables do not interfere with each other.

Are you ready? The killer trial begins!

1. Killers usually warm up before going out

do = {
  get exercise() {
    delete do.exercise
    return do.exercise
  }
}
do.exercise
Copy the code

【 A 】 undefined
[B] null
[C] Stack overflow error
D

Answers and explanations (don’t peek)

D) Uncaught SyntaxError: Unexpected token ‘=’

2. Don’t forget to check your body armor and ammo before going out

; [Number.isNaN('AK-103'), isNaN('Bullet (7.62 x 39mm BP) ')]
Copy the code

【 A 】 true, true
[B] false and true
[C] false, false
[D] true, false

Answers and explanations (don’t peek)

In general, isNaN does toNumber conversions to incoming values, while number. isNaN does not. Number.isNaN is a more “correct” version of isNaN semantics. See specification for specific algorithm.

3. Insert the key and open the door

; (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')
Copy the code

【A】undefined
[B] sunR
[C] sunL
【D】sunR, sunR

Answers and explanations (don’t peek)

[D] The binding behavior of parameter types is similar to that of VarDeclaration. The later bound identifier overrides the first bound identifier. In addition, the specification mentions that only functions with simple argument lists (with no parameter defaults) and code running in non-strict mode support this behavior. Note that use strict needs to be at the beginning of the code environment to be useful

4. Accelerating, hold on!

; (function(x = 1.undefined, y = 2) {
  return [...arguments].reduce((speed, acceleration) = > speed + acceleration, 0)
})()
Copy the code

[A] 0
[B] 1
[C] 2
[D]. 3

Answers and explanations (don’t peek)

[C] argumentargumentsargumentsargumentsargumentsargumentsargumentsargumentsargumentsargumentsargumentsargumentsargumentsarguments

5. Find your target while driving

; [function() {}.__proto__ === Function.prototype,
  Function.prototype === Object.prototype,
  Function.__proto__ === Object.__proto__,
  Function.prototype.__proto__ === Object.prototype
].filter(Boolean).length
Copy the code

[A] 0
[B] 1
[C] 2
[D]. 3

Answers and explanations (don’t peek)

D) The archetypal chain is something that both ninjas and killers have to master and memorize. Specific can be Kangkang Hursh Jain JS prototype chain picture, very clear, can open the door for you to the new world.

6. I finally found my purpose!

var target = {
  seen() {
    console.log(this=== target) } } ; ('haha', target.seen)()
Copy the code

【 A 】 true
[B] false
[C] wrong
[D] undefined

Answers and explanations (don’t peek)

The specification states that the expression will return a “value” for the target.seen identifier. This “value” does not carry computation-time context information. You can imagine assigning a target.seen value to a variable and then calling that variable alone, so this points to window instead of target.

7. Sabotage alarm ~

/* Note: in the browser environment, two pieces of code are executed separately to prevent variable promotion */
// Execute the three lines first (break the alarm on the left)
var alert = (. args) = > console.log(args)
delete alert
console.log(typeof window.alert)
// Execute these three lines (break the alarm on the right)
var alert = (. args) = > console.log(args)
delete alert
console.log(typeof window.alert)
Copy the code

【A】undefined, undefined
【B】undefined, function
【C】function, function
【D】undefined

Answers and explanations (don’t peek)

If the global object does not have this property, it will go through the normal process of declaring variables, so the second output is function. The second, less well known, is that if the global object has this property, the binding of the declared identifier to its value is recorded via the Environment Record property VarNames. This record, unlike normal variable declarations, is modifiable and can be verified with the following code:

// Test var alert = (… args) => console.log(args) Object.getOwnPropertyDescriptor(window, ‘alert’) // >>> {writable: true, enumerable: ƒ}

The specifications are CreateGlobalVarBinding and Delete Operator.

By the way, many bloggers say that the length property of the function has the meta-dontdelete property, which is true and therefore cannot be deleted, Since ES5, DontDelete is replaced with an internal property equal to different information. According to the new specification, the internal property of the length property is configured with true, and therefore is “removable”. You can open the browser console, try creating a function, and remove its Length property, and see that it returns true.

8. Count the distance and aim!

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)
Copy the code

【 A 】 false, false
[B] true, true
[C] true, false
[D] false and true

Answers and explanations (don’t peek)

C) operator associativity and implicit conversion. The relational operator is left associative and the assignment operator is right associative, so 1<2<3 is (1<2)<3, and x=y=z is x=(y=z). From the assignment statement, target and killer refer to the same object, so in the assignment statement, target.x (killer. X, killer. X) gets the “value” of “target is assigned to 1”, and target is assigned to 1. So at the end of the assignment, killer.x is 1 and target is 1. The final output compares 1<2<3 and undefined

9. BANG!

; [void "killer's target"= = =typeof down,
  delete void "killer's target"= = =delete undefined.delete undefined= = =delete null
].filter(Boolean).length
Copy the code

[A] 0
[B] 1
[C] 2
[D]. 3

Answers and explanations (don’t peek)

The Void operator returns undefined, but undefined is not the same as typeof down, so the first line of false is missing. If null is deleted, it returns true. If Undefined is deleted, it returns false. The delete operator can delete undefined without any additional information, because the delete operator can locate the descriptor of undefined without any additional information, and its internal property is false. Void ‘string’ returns undefined, undefined ‘value’. As abstract as it sounds, let’s take the following code as an example:

delete NaN; // false +’string’; // NaN delete +’string’; // true

NaN is not deletable, but our expression +’string’ returns NaN as a “value”, so delete +’string’ falls back to “delete a value”, which returns true as per the specification. Delete void “killer’s target” in this example, you need to clear your mind before you understand it.

10. “Evil” emotions grow inside!

// Side: Heart and Ghost are never defined variables
eval(`typeof typeof ghost === typeof The ${typeof heart}`)
Copy the code

[A] wrong
[B] undefined
[C] true
[D] false

Answers and explanations (don’t peek)

D) undefined is returned if the expression on the right side of the typeof is an invalid reference (UnresolvableReference) or undefined. See specification: Typeof. The result of template string instantiation will be “typeof Typeof ghost === typeof undefined” so it will be false.

11 before the road, heart demons hit 😈 again, it will drown you?

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)')
})()
Copy the code

【A】dead alive dead
【B】dead alive
【C】alive dead alive
【D】alive dead

Answers and explanations (don’t peek)

An eval() function is called a “direct call”, whereas “(0, eval)()” is called an “indirect call”. The difference between eval(0, eval)() and this is the variable context. Kangax’s Global Eval. What Are the Options? A detailed description of how to distinguish the two can be used as a guide. Function Calls Evaluation, Runtime Semantics: PerformEval

12. SAN (Sanity) goes insane!

Will console.log in // finally output?
// Does the return statement return?; (function() {
  let san = 3
  try {
    --san
    return san
  } finally {
    --san
    console.log(san)
  }
})()
Copy the code

[A] Output 1, return 2
[B] Output 1, no return
[C] Output 1, return 1
【D】 No output, return 2

Answers and explanations (don’t peek)

5. This question should be the most curious of all breeds. This kind of code can’t be understood in the normal programming mind, so you have to go back to killer camp (language specification) to find a solution. It is common to think that executing until return will “end the function run,” but this undermines the conceptual integrity of “finally” (i.e., run anyway). Therefore, the first two steps in describing the execution behavior of a try Finally statement are to execute the statement in the try and the statement in the finally respectively, and then determine what the entire try Finally ultimately returns based on their return types (such as throw, Break, and return normally). At execution time, the value of the return in the try is already determined, so changes made to the SAN in finally have no effect on the return in the try. For more details, see the TryStatement section of the specification. As an added bonus, it’s not just expressions that have a “value” in JS, but also statements (although the “value” is not the same thing). For ease of understanding, you can think of the “value” of the return statement as “{type: ‘return’, value: ‘… ‘} ‘, there is no JS API to get the type attribute in a statement’s value. You can only get the value of a statement with a syntax such as’ eval(‘”string”‘). As long as you understand that statements have “values” in JS, you can imagine that the engine can save and pass the result of a return statement.

13. Let’s do some math and come to your senses

; [// kill 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
Copy the code

[A] 0
[B] 1
[C] 2
[D]. 3

Answers and explanations (don’t peek)

The first question is very classic, and it is not only in JS. JS’s numeric system uses IEEE 754 double-precision floating-point standard to store floating-point numbers in 64 bits, so certain decimal bits that are too long cannot be stored. This means that the decimal number we enter in the REPL corresponds to a larger or smaller value that is actually stored in the engine. So we’re really comparing whether a number approximately equal to 0.1 plus a number approximately equal to 0.2 equals a number approximately equal to 0.3. MAX_SAFE_INTEGER (MDN Number.MAX_VALUE); MAX_VALUE (MDN Number.MAX_VALUE)

14. Put your “luggage” in the trunk and go home!

drivetime = 0
isArived = false
console.log('go')
setTimeout(() = > (isArived = true), 0)
while(++drivetime && ! isArived) {}console.log('home')
Copy the code

【 A 】 ‘go’, ‘home’
[B] ‘go’
[C] ‘home’
【D】Empty Log

Answers and explanations (don’t peek)

A) Event Loop B) Event Loop C) Event Loop D) Event Loop The interesting thing is that it is defined by the HTML5 specification, not the ES specification. This makes sense when you think about it, because timers are provided by the host environment, not the Javascript language itself.

15. Avoid manhole covers while driving!

; [// DEX + 100!
  +0= = = -0.String(+0) = = =String(-0),
  +0 * 'hole'= = = -0 * 'hole'.1 / +0= = =1 / -0
].filter(Boolean).length
Copy the code

[A] 0
[B] 1
[C] 2
[D]. 3

Answers and explanations (don’t peek)

C) The positive and negative zeros are equal to each other. To a string, no sign, so the second one is also true; NaN does not equal NaN, and the third clause is false; Infinity is not equal to minus Infinity, and the last one is false. If you want to distinguish between a “zero” and a “zero” in JS, you can use the fourth code to demonstrate the division rule.

To read more

Hi, how are you? How do you feel about drinking more hot water? Did you enjoy this unique challenge?

Although the title of the article is a mirage, and the title has little to do with programming practice, I’m really just trying to get you interested in language norms. The language specification is so important that learning the specification will help you understand the language more deeply, how the engine works, how the AST behaves, and the dark arts of the various framework code, rather than just being a user of it. ‘.

If you’re still not satisfied, you can continue to try these puzzles (Nene, don’t forget to give me a like first) :

  • Javascript Quiz (2013)
  • Javascript Puzzlers