この投稿は、楽しくてトリッキーなJavaScriptの例のリストです。 これは素晴らしい言語です。 シンプルな構文、大規模なエコシステム、そしてさらに重要なことに、巨大なコミュニティがあります。
同時に、JavaScriptはややこしいことをするかなりおもしろい言語であることを皆知っています。 そのうちのいくつかは、私たちの毎日の仕事をすぐに地獄に変えてしまいます。 この投稿では、それらのいくつかを検討します。
内容
- やる気
- 表記法
- 例
- []は同等です![]
- trueはfalse
- バナナ
- NaNではなくNaN
- 失敗する
- []は「true」(真実)ですが、trueではありません
- nullは「偽」ですが、偽ではありません
- ゼロより大きい最小値
- 関数は関数ではありません
- 配列の追加
- コンマを配列にぶら下げ
- 配列の等価性は怪物です
- 未定義および番号
- 不正なparseInt
- 真と偽で計算する `
- HTMLコメントはJavaScriptで有効です
- ナン
じゃない数字です - []とnullはオブジェクトです
- 数の魔法の増加
- 精度0.1 + 0.2
- パッチ番号
- 3つの数値の比較
- 面白い数学
- 正規表現の追加
- 文字列は文字列のインスタンスではありません
- バックティックを使用した関数の呼び出し(バックティック)
- コールコールコール
- コンストラクタープロパティ
- オブジェクトプロパティキーとしてのオブジェクト
- プロトによるプロトタイピング
- $ {{オブジェクト}}
- デフォルト値での再構築
- ポイントと分布
- タグ
- ネストされたタグ
- 陰湿なtry..catch
- これは多重継承ですか?
- 自身からデータを受け取るジェネレーター
- クラスクラス
- 暗黙の型変換が無効なオブジェクト(非強制オブジェクト)
- トリッキーアロー機能
- トリッキーなリターン
- 配列を使用したオブジェクトプロパティへのアクセス
- その他の情報源
やる気
楽しみのために
- 「楽しみのために:偶然の革命家の物語」 、リーナス・トーバルズ
このリストの主な目標は、いくつかのクレイジーな例を収集し、可能であればそれらがどのように機能するかを説明することです。 前に知らなかったことを学ぶのはいいことだからです。
初めての方は、これらのメモを使用して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
:
:
-
Type(x)
Type(y)
, false. -
Type(x)
,
- x NaN, false.
- y NaN, false.
- … … …
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
:
:
- ,
n
+0
. -
n
? ToNumber (value)
. -
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
console.log.call.call.call.call.call.apply(a => a, [1, 2])
:
, ! : call
apply
. :
- 19.2.3.3 Function.prototype.call (thisArg, ...args)
- 19.2.3.1 Function.prototype.apply (thisArg, argArray)
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
-
x
,undefined
. -
x
x
. -
x
,y
. ,1
. -
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'`
- wtfjs.com — , .
- Wat — CodeMash 2012.
- What the… JavaScript? — « » JavaScript. , , , open source-.