1. Non-coercible objects
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
}
// objects
const foo = nonCoercible({foo: 'foo'})
foo * 10 // -> TypeError: Trying to coerce non-coercible object
foo + 'evil' // -> TypeError: Trying to coerce non-coercible object
// strings
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
// numbers
const baz = nonCoercible(1)
baz == 1 // -> TypeError: Trying to coerce non-coercible object
baz === 1 // -> false
baz.valueOf() === 1 // -> true
ToPrimitive ( input [ , PreferredType ] )
- Assert: input is an ECMAScript language value.
- If Type(input) is Object, then
2.a If PreferredType was not passed, let hint be "default".
2.b Else if PreferredType is hint String, let hint be "string".
2.c Else PreferredType is hint Number, let hint be "number".
2.d Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
2.e If exoticToPrim is not undefined, then
2.e.(1) Let result be ? Call(exoticToPrim, input, « hint »).
2.e.(2) If Type(result) is not Object, return result.
2.e.(3) Throw a TypeError exception.
2.f If hint is "default", set hint to "number".
2.g Return ? OrdinaryToPrimitive(input, hint).- Return input.
OrdinaryToPrimitive ( O, hint )
- Assert: Type(O) is Object.
- Assert: Type(hint) is String and its value is either "string" or > "number".
- If hint is "string", then
3.a Let methodNames be « "toString", "valueOf" ».- Else,
4.a Let methodNames be « "valueOf", "toString" ».- For each name in methodNames in List order, do
5.a Let method be ? Get(O, name).
5.b If IsCallable(method) is true, then
5.b.(1) Let result be ? Call(method, O).
5.b.(2) If Type(result) is not Object, return result.- Throw a TypeError exception.
6.1.5.1 Well-Known Symbols
19.4.2.12 Symbol.toPrimitive
7.1.1 ToPrimitive ( input [ , PreferredType ] )
7.1.3 ToNumber ( argument )
7.1.12ToString ( argument )
2. try ... finally
(() => {
try {
return 2;
} finally {
return 3;
}
})(); // 3
TryStatement : try Block Catch Finally
- Let B be the result of evaluating Block.
- If B.[[Type]] is throw, let C be CatchClauseEvaluation of Catch with parameter B.[[Value]].
- Else, let C be B.
- Let F be the result of evaluating Finally.
- If F.[[Type]] is normal, set F to C.
- Return Completion(UpdateEmpty(F, undefined)).
13.15.8 Runtime Semantics: Evaluation
3. Labelled statements
foo: {
console.log('first');
break foo;
console.log('second');
} // first
foo:{
while(true){
break foo;
}
console.log(1);
}
console.log(2); // 2
A Statement may be prefixed by a label. Labelled statements are only used in conjunction with labelled break and continue statements. ECMAScript has no goto statement.
4. Arithmetics
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
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
- Let lref be the result of evaluating AdditiveExpression.
- Let lval be ? GetValue(lref).
- Let rref be the result of evaluating MultiplicativeExpression.
- Let rval be ? GetValue(rref).
- Let lprim be ? ToPrimitive(lval).
- Let rprim be ? ToPrimitive(rval).
- If Type(lprim) is String or Type(rprim) is String, then
7.a Let lstr be ? ToString(lprim).
7.b Let rstr be ? ToString(rprim).
7.c Return the String that is the result of concatenating lstr and rstr.- Let lnum be ? ToNumber(lprim).
- Let rnum be ? ToNumber(rprim).
- Return the result of applying the addition operation to lnum and rnum.
12.8.3 The Addition Operator ( + )
7.1.1 ToPrimitive ( input [ , PreferredType ] )
7.1.12ToString ( argument )
7.1.3 ToNumber ( argument )
5. Numbers
999999999999999 // -> 999999999999999
9999999999999999 // -> 10000000000000000
10000000000000000 // -> 10000000000000000
10000000000000000 + 1 // -> 10000000000000000
10000000000000000 + 1.1 // -> 10000000000000002
0.1 + 0.2 // -> 0.30000000000000004
6.1.6 The Number Type
0.30000000000000004.com
6. HTML comments
// valid comment
<!-- valid comment too
7. Array
[] == '' // -> 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
Abstract Equality Comparison
- If Type(x) is the same as Type(y), then
1.a Return the result of performing Strict Equality Comparison x === y.- If x is null and y is undefined, return true.
- If x is undefined and y is null, return true.
- If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
- If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
- If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
- If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
- If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
- If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
- Return false.
7.2.13 Abstract Equality Comparison
8. Trailing commas in array
let a = [,,,]
a.length // -> 3
a.toString() // -> ',,'
9. [] is equal ![]
[] == ![] // -> true
7.2.13 Abstract Equality Comparison
12.5.9 Logical NOT Operator ( ! )
网友评论