一体何、Javascript







この投稿は、楽しくてトリッキーなJavaScriptの例のリストです。 これは素晴らしい言語です。 シンプルな構文、大規模なエコシステム、そしてさらに重要なことに、巨大なコミュニティがあります。







同時に、JavaScriptはややこしいことをするかなりおもしろい言語であることを皆知っています。 そのうちのいくつかは、私たちの毎日の仕事をすぐに地獄に変えてしまいます。 この投稿では、それらのいくつかを検討します。







内容





やる気



楽しみのために

- 「楽しみのために:偶然の革命家の物語」 、リーナス・トーバルズ

このリストの主な目標は、いくつかのクレイジーな例を収集し、可能であればそれらがどのように機能するかを説明することです。 前に知らなかったことを学ぶのはいいことだからです。







初めての方は、これらのメモを使用してJavaScriptの詳細をご覧ください。 この記事が仕様を読むのにより多くの時間を費やすよう動機付けられることを願っています。 あなたがプロの開発者であれば、これらの例を、私たちの愛するJavaScriptのすべてのトリックとサプライズの良いリファレンスと考えることができます。 いずれにしても、読んでください。 あなたはおそらくあなた自身のために新しい何かを見つけるでしょう。







表記法



// ->



. :







1 + 1 // -> 2
      
      





// ->



console.log



. :







console.log('hello, world!') // -> hello, world!
      
      





//



. :







//    foo
const foo = function () {}
      
      







[] ![]



:







[] == ![] // -> true
      
      





:





true false



!!'false' ==  !!'true'  // -> true
!!'false' === !!'true' // -> true
      
      





:



:







true == 'true'    // -> true
false == 'false'  // -> false
      
      





// 'false'



, «» (truthy)







!!'false' // -> true
!!'true'  // -> true
      
      







baNaNa



'b' + 'a' + + 'a' + 'a'
      
      





JavaScript, . :







'foo' + + 'bar' // -> 'fooNaN'
      
      





:



'foo' + (+'bar')



, 'bar'



.









NaN NaN



NaN === NaN // -> false
      
      





:



:







  1. Type(x)



    Type(y)



    , false.
  2. Type(x)



    ,

    1. x NaN, false.
    2. y NaN, false.
    3. … … …




NaN



IEEE:







: , , , (unordered). , NaN. NaN , .

“What is the rationale for all comparisons returning false for IEEE754 NaN values?”


fail



, …







(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
// -> 'fail'
      
      





:



, :







(![]+[]) // -> 'false'
![]      // -> false
      
      





[]



false



. - (binary + Operator -> ToPrimitive -> [[DefaultValue]]



) :







(![]+[].toString()) // -> 'false'
      
      





, [0]



:







'false'[0] // -> 'f'
      
      





, i



. i



fail



'falseundefined'



['10']









[] «», true



«» (truthy) , , , true



.







!![]       // -> true
[] == true // -> false
      
      





:



ECMA-262:









null «», false



, null



«» (falsy) , false



.







!!null        // -> false
null == false // -> false
      
      





«» , 0



''



, false



.







0 == false  // -> true
'' == false // -> true
      
      





:



, :











Number.MIN_VALUE



:







Number.MIN_VALUE > 0 // -> true
      
      





:



Number.MIN_VALUE



5e-324



, , (float precision), . , .







Number.NEGATIVE_INFINITY



, .











V8 v5.5 (Node.js <=7). «undefined is not a function», ?







//  ,  null
class Foo extends null {}
// -> [Function: Foo]

new Foo instanceof null
// -> TypeError:    
// ->     at … … …
      
      





:



. , , .









?







[1, 2, 3] + [4, 5, 6]  // -> '1,2,34,5,6'
      
      





:



. :







[1, 2, 3] + [4, 5, 6]
//  toString()
[1, 2, 3].toString() + [4, 5, 6].toString()
// 
'1,2,3' + '4,5,6'
// ->
'1,2,34,5,6'
      
      







. - :







let a = [,,,]
a.length     // -> 3
a.toString() // -> ',,'
      
      





:



( « ») JavaScript- , . , , . , .















JS , :







[] == ''   // -> true
[] == 0    // -> true
[''] == '' // -> true
[0] == 0   // -> true
[0] == ''  // -> false
[''] == 0  // -> true

[null] == ''      // true
[null] == 0       // true
[undefined] == '' // true
[undefined] == 0  // true

[[]] == 0  // true
[[]] == '' // true

[[[[[[]]]]]] == '' // true
[[[[[[]]]]]] == 0  // true

[[[[[[ null ]]]]]] == 0  // true
[[[[[[ null ]]]]]] == '' // true

[[[[[[ undefined ]]]]]] == 0  // true
[[[[[[ undefined ]]]]]] == '' // true
      
      





:



! , 7.2.13 .







undefined Number



Number



, 0



. , undefined



, Number



undefined



. undefined



, NaN



.







Number()          // -> 0
Number(undefined) // -> NaN
      
      





:



:







  1. , n



    +0



    .
  2. n



    ? ToNumber (value)



    .
  3. undefined



    , ToNumber(undefined)



    NaN



    .


:









parseInt



parseInt



:







parseInt('f*ck');     // -> NaN
parseInt('f*ck', 16); // -> 15
      
      





:



, parseInt



, . f



'f*ck'



15



.







Infinity



:







//
parseInt('Infinity', 10) // -> NaN
// ...
parseInt('Infinity', 18) // -> NaN...
parseInt('Infinity', 19) // -> 18
// ...
parseInt('Infinity', 23) // -> 18...
parseInt('Infinity', 24) // -> 151176378
// ...
parseInt('Infinity', 29) // -> 385849803
parseInt('Infinity', 30) // -> 13693557269
// ...
parseInt('Infinity', 34) // -> 28872273981
parseInt('Infinity', 35) // -> 1201203301724
parseInt('Infinity', 36) // -> 1461559270678...
parseInt('Infinity', 37) // -> NaN
      
      





null



:







parseInt(null, 24) // -> 23
      
      





:



null



"null"



, . 0 23 , , NaN



. 24 "n"



, 14- , . 31 "u"



, 21- , , . 37 , NaN



.







“parseInt(null, 24) === 23… , ?”







(octal):







parseInt('06'); // 6
parseInt('08'); // 8 if support ECMAScript 5
parseInt('08'); // 0 if not support ECMAScript 5
      
      





:



"0", 8 () 10 (). . ECMAScript 5 10, . parseInt



.







parseInt



:







parseInt({ toString: () => 2, valueOf: () => 1 }) // -> 2
Number({ toString: () => 2, valueOf: () => 1 })   // -> 1
      
      





true



false





:







true + true // -> 2
(true + true) * (true + true) - true // -> 3
      
      











:



Number



. , true



1



:







Number(true) // -> 1
      
      





. , true



, false



null



. , NaN



. true



1



:







+true // -> 1
      
      





, ToNumber



. , :







argument



true, 1. argument



false, +0.

.







:









HTML- JavaScript



, HTML- <!--



JavaScript.







//  
<!--   
      
      





:



? - HTML (degrade gracefully) , <script>



. , Netscape 1.x, . HTML- .







Node.js V8, HTML- runtime- Node.js. , :









NaN



NaN



'number'



:







typeof NaN            // -> 'number'
      
      





:



typeof



instanceof



:









[] null



typeof []   // -> 'object'
typeof null // -> 'object'

// 
null instanceof Object // false
      
      





:



typeof



:









, typeof



35: typeof



. null



, , , [[Call]]



, "object"



.







toString



.







Object.prototype.toString.call([])
// -> '[object Array]'

Object.prototype.toString.call(new Date)
// -> '[object Date]'

Object.prototype.toString.call(null)
// -> '[object Null]'
      
      







999999999999999  // -> 999999999999999
9999999999999999 // -> 10000000000000000

10000000000000000       // -> 10000000000000000
10000000000000000 + 1   // -> 10000000000000000
10000000000000000 + 1.1 // -> 10000000000000002
      
      





:



IEEE 754-2008 . :









0.1 + 0.2



. 0.1



0.2



:







0.1 + 0.2 // -> 0.30000000000000004
(0.1 + 0.2) === 0.3 // -> false
      
      





:



StackOverflow ” ?”:







0.2



0.3



. , 0.2



double



0.2



, 0.3



double



0.3



. 0.1



0.2



0.3



, .

, 0.30000000000000004.com. , , JavaScript.









- Number



String



.







Number.prototype.isOne = function () {
  return Number(this) === 1
}

1.0.isOne() // -> true
1..isOne()  // -> true
2.0.isOne() // -> false
(7).isOne() // -> false
      
      





:



, Number



, JavaScript. , . Number



:











1 < 2 < 3 // -> true
3 > 2 > 1 // -> false
      
      





:



? . :







1 < 2 < 3 // 1 < 2 -> true
true  < 3 // true -> 1
1     < 3 // -> true

3 > 2 > 1 // 3 > 2 -> true
true  > 1 // true -> 1
1     > 1 // -> false
      
      





« »



:







3 > 2 >= 1 // true
      
      





:











JavaScript . :







 3  - 1  // -> 2
 3  + 1  // -> 4
'3' - 1  // -> 2
'3' + 1  // -> '31'

'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'

'222' - -'111' // -> 333

[4] * [4]       // -> 16
[] * []         // -> 0
[4, 4] * [4, 4] // NaN
      
      





:



? , JavaScript:







Number  + Number  -> 
Boolean + Number  -> 
Boolean + Boolean -> 
Number  + String  -> 
String  + Boolean -> 
String  + String  -> 
      
      





? []



{}



, ToPrimitive



ToString



. :











 ,     ?
//    toString
RegExp.prototype.toString = function() {
  return this.source
}

/7/ - /5/ // -> 2
      
      





:





String



'str' // -> 'str'
typeof 'str' // -> 'string'
'str' instanceof String // -> false
      
      





:



String



:







typeof String('str')   // -> 'string'
String('str')          // -> 'str'
String('str') == 'str' // -> true
      
      





new



:







new String('str') == 'str' // -> true
typeof new String('str')   // -> 'object'
      
      





? ?







new String('str') // -> [String: 'str']
      
      





String:









« » (backticks)



, :







function f(...args) {
  return args
}
      
      





, :







f(1, 2, 3) // -> [ 1, 2, 3 ]
      
      





, « »?







f`true is ${true}, false is ${false}, array is ${[1,2,3]}`
// -> [ [ 'true is ', ', false is ', ', array is ', '' ],
// ->   true,
// ->   false,
// ->   [ 1, 2, 3 ] ]
      
      





:



, (Tagged template literals). f



. . - . . :







function template(strings, ...keys) {
  // -     …
}
      
      





, styled-components, React-.









Call call call



@cramforce







console.log.call.call.call.call.call.apply(a => a, [1, 2])
      
      





:



, ! : call



apply



. :









constructor



const c = 'constructor'
c[c][c]('console.log("WTF?")')() // -> WTF?
      
      





:



:







//   ,     'constructor'
const c = 'constructor'

// c —   
c // -> 'constructor'

//   
c[c] // -> [Function: String]

//   
c[c][c] // -> [Function: Function]

//   Function        
c[c][c]('console.log("WTF?")') // -> [Function: anonymous]

//      
//     'WTF?'
c[c][c]('console.log("WTF?")')() // -> WTF?
      
      





Object.prototype.constructor



- Object



, -. String



, Number



, .











{ [{}]: {} } // -> { '[object Object]': {} }
      
      





:



? (Computed property name). , , '[object Object]'



{}



.







« »:







({[{}]:{[{}]:{}}})[{}][{}] // -> {}

// structure:
// {
//   '[object Object]': {
//     '[object Object]': {}
//   }
// }
      
      





:









proto



, . __proto__



, :







(1).__proto__.__proto__.__proto__ // -> null
      
      





:



- , - ToObject



. :







(1).__proto__ // -> [Number: 0]
(1).__proto__.__proto__ // -> {}
(1).__proto__.__proto__.__proto__ // -> null
      
      





__proto__



:









${{Object}}



?







`${{Object}}`
      
      





:







// -> '[object Object]'
      
      





:



Object



(Shorthand property notation):







{ Object: Object }
      
      





, toString



. '[object Object]'



.











:







let x, { x: y = 1 } = { x }; y;
      
      





. y



? :







// -> 1
      
      





:



let x, { x: y = 1 } = { x }; y;
//  ↑       ↑           ↑    ↑
//  1       3           2    4
      
      





  1. x



    , undefined



    .
  2. x



    x



    .
  3. x



    , y



    . , 1



    .
  4. y



    .




(spreading)



.







[...[...'...']].length // -> 3
      
      





:



3



? TODO, @@iterator



, , , . , . .







'...'



.



, 3



.







:







[...'...']             // -> [ '.', '.', '.' ]
[...[...'...']]        // -> [ '.', '.', '.' ]
[...[...'...']].length // -> 3
      
      





, :







[...'...']                 // -> [ '.', '.', '.' ]
[...[...'...']]            // -> [ '.', '.', '.' ]
[...[...[...'...']]]       // -> [ '.', '.', '.' ]
[...[...[...[...'...']]]]  // -> [ '.', '.', '.' ]
//   …
      
      







JavaScript. :







foo: {
  console.log('first');
  break foo;
  console.log('second');
}

// -> first
// -> undefined
      
      





:



break



continue



. , break



continue



, .







foo



. console.log('first');



.







JavaScript:











a: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -> 5
      
      





:



, :









try..catch



? 2



3



?







(() => {
  try {
    return 2;
  } finally {
    return 3;
  }
})()
      
      





3



. ?







:





?



:







new (class F extends (String, Array) { }) // -> F []
      
      





? .







:



extends ((String, Array))



. , (String, Array)



Array



. , Array



.









,



:







(function* f() { yield f })().next()
// -> { value: [GeneratorFunction: f], done: false }
      
      





, , value



f



. :







(function* f() { yield f })().next().value().next()
// -> { value: [GeneratorFunction: f], done: false }

//  
(function* f() { yield f })().next().value().next().value().next()
// -> { value: [GeneratorFunction: f], done: false }

//  
(function* f() { yield f })().next().value().next().value().next().value().next()
// -> { value: [GeneratorFunction: f], done: false }

//   
// …
      
      





:



, , :











:







(typeof (new (class { class () {} }))) // -> 'object'
      
      





, . , 'object'



.







:



ECMAScript 5 . :







const foo = {
  class: function() {}
};
      
      





ES6 . . : function



, :







class {
  class() {}
}
      
      





. typeof



'object'



.







:









, (Non-coercible objects)



Well-Known Symbols :







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
}
      
      





:







// 
const foo = nonCoercible({foo: 'foo'})

foo * 10      // -> TypeError: Trying to coerce non-coercible object
foo + 'evil'  // -> TypeError: Trying to coerce non-coercible object

//  
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

// 
const baz = nonCoercible(1)

baz == 1             // -> TypeError: Trying to coerce non-coercible object
baz === 1            // -> false
baz.valueOf() === 1  // -> true
      
      





:







:







let f = () => 10
f() // -> 10
      
      





, , :







let f = () => {}
f() // -> undefined
      
      





:



{}



undefined



. , , f



.









:







(function () {
  return
  {
    b : 10
  }
})() // -> undefined
      
      





:



return



:







(function () {
  return {
    b : 10
  }
})() // -> { b: 10 }
      
      







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
      
      





:



[]



toString



. — :







['property'].toString() // -> 'property'`
      
      










All Articles