JavaScriptクイズ「x + 0 == x - 0」
筆者は7個まちがえて65/100点でございました。とはいえ、実際の動きを調べてみたら偶然結果が当たっていただけのこともあり、点数ほどは理解出来ていません。ちなみに、動作確認した処理系は、"node.js v0.7.5-pre"。
まずは、1問目の解説から。
まずは、左辺がどのように展開されるかの解説。
{}+0
- ToPrimitive({}, PreferredType=Number)+0
// No hint for PreferredType then default "Number".
// See 8.6.2.6 [[DefaultValue]](hint).
When the [[DefaultValue]] method of O is called with no hint, then it behaves as if the hint were Number
- {}.toString()+0
// See 8.6.2.6 [[DefaultValue]](hint)
5. Call the [[Get]] method of object O with argument "toString".
// ここ自信無い - '[object Object]'+0
- '[object Object]'+0.toString()
// Because Type(ToPrimitive({},PreferredType=Number)) is String.
// See 11.6.1 The Addition operator (+ )
7.If Type(Result(5)) is String or Type(Result(6)) is String, go to step 12
12. Call ToString(Result(5)).
13. Call ToString(Result(6)). - '[object Object]0'
うーん、しんどい。お次は、右辺。
{}-0
- ToNumber({})-ToNumber(0)
// ToNumber() is called because the operator "-" is applied to only "Number" type.
// See 11.6.2 The Subtraction Operator (- ) - ToNumber('[object Object]')-ToNumber(0)
// ToPrimitive(x, PreferredType=Number) is called, and ToNumber() is called.
// See 9.3 ToNumber - NaN-0
- NaN
// See 11.6.3 Applying the Additive Operators ( +,- ) to Numbers
either operand is NaN, the result is NaN.
最後に、左辺と右辺の比較の解説
See 11.9.3 The Abstract Equality Comparison Algorithm.
'[object Object]0'==NaN
- ToNumber('[object Object]0')==NaN
// 1. If Type(x) is different from Type(y), go to step 14.
// 17.If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x)== y. - NaN==NaN
- false
// 5.If x is NaN, return false.
うーん、これでもいくつかはしょってるけど、まじめに解説するとめっちゃ大変(どっか間違ってたら、ご指摘願います)。こっからはがしがしはしょっていきます。
[]+0==[]-0
- [].toString()+0==ToNumber([])-0
- ''+0==0-0
- '0'==0
- ToNumber('0')==0
- 0==0
- true
[].toString() returns ''
ToNumber([]) returns 0
(function(){})+0==(function(){})-0
- (function(){}).toString()+0==ToNumber((function(){}))-0
- 'function (){}'+0==NaN-0
- 'function (){}0'==NaN
- ToNumber('function (){}0')==NaN
- NaN==NaN
- false
null+0==null-0
- ToNumber(null)+0==ToNumber(null)-0
- 0+0==0-0
- 0==0
- true
See 9.3 ToNumber.
undefined+0==undefined-0
- ToNumber(undefined)+0==ToNumber(undefined)-0
- NaN+0==NaN-0
- NaN==NaN
- false
See 9.3 ToNumber.
Infinity+0==Infinity-0
- Infinity==Infinity
- true
Array+0==Array-0
- Array.toString()+0==ToNumber(Array)-0
- 'function Array() { [native code] }'+0==NaN-0
- 'function Array() { [native code] }0'==NaN
- ToNumber('function Array() { [native code] }0')==NaN
- NaN==NaN
- false
0+0==0-0
- true
false+0==false-0
- ToNumber(false)+0==ToNumber(false)-0
- 0+0==0-0
- true
See 9.3 ToNumber.
NaN+0==NaN-0
- NaN==NaN
- false
If either operand is NaN, the result is NaN.
""+0==""-0
- ToString("")+ToString(0)==ToNumber("")-0
// 7.If Type(Result(5)) is String or Type(Result(6)) is String, go to step 12.
// 12. Call ToString(Result(5)).
// 9.Call ToNumber(Result(6)). - ''+'0'==0-0
- '0'==0
- ToNumber('0')==0
- 0==0
- true
See 9.3.1 ToNumber Applied to the String Type.
A StringNumericLiteral that is empty or contains only white space is converted to +0.
"a"+0=="a"-0
- ToString("a")+ToString(0)==ToNumber("a")-0
- 'a'+'0'==NaN-0
- 'a'==NaN
- ToNumber('a')==NaN
- NaN==NaN
- false
"0"+0=="0"-0
- ToString("0")+ToString(0)==ToNumber("0")-0
- '0'+'0'==0-0
- '00'==0
- ToNumber('00')==0
- 0==0
- true
"1"+0=="1"-0
- ToString("1")+ToString(0)==ToNumber("1")-0
- '1'+'0'==1-0
- '10'==1
- ToNumber('10')==1
- 10==1
- false
"0.1"+0=="0.1"-0
- ToString("0.1")+ToString(0)==ToNumber("0.1")-0
- '0.1'+'0'==0.1-0
- '0.10'==0.1
- ToNumber('0.10')==0.1
- 0.1==0.1
- true
"0x"+0=="0x"-0
- ToString("0x")+ToString(0)==ToNumber("0x")-0
- '0x'+'0'==NaN-0
- '0x0'==NaN
- ToNumber('0x0')==NaN
- 0==NaN
- false
See 9.3.1 ToNumber Applied to the String Type.
"."+0=="."-0
- ToString(".")+ToString(0)==ToNumber(".")-0
- '.'+'0'==NaN-0
- '.0'==NaN
- ToNumber('.0')==NaN
- 0==NaN
- false
See 9.3.1 ToNumber Applied to the String Type.
" "+0==" "-0
- ToString(" ")+ToString(0)==ToNumber(" ")-0
- ' '+'0'==0-0
- ' 0'==0
- ToNumber(' 0')==0
- 0==0
- true
StringNumericLiteral:::StrWhiteSpace(opt) StrNumericLiteral StrWhiteSpace(opt)
A StringNumericLiteral that is empty or contains only white space is converted to +0.
Array()+0==Array()-0
- []+0==[]-0 あとは、2問目と同様。
- [].toString()+0==ToNumber([])-0
- ''+0==0-0
- '0'==0
- ToNumber('0')==0
- 0==0
- true
it creates and initialises a new Array object.うーん、これは知らなかった。
See JavaScript: new無しで基本型のコンストラクタを呼んだ時の挙動.
(function(){}())+0==(function(){}())-0
- undefined+0==undefined-0 あとは、5問目と同様。
- ToNumber(undefined)+0==ToNumber(undefined)-0
- NaN+0==NaN-0
- NaN==NaN
- false
ReturnStatement : return [no LineTerminator here] Expression(opt);
If Expression is omitted, the return value is undefined.
ここまで読んでくださったみなさま、ありがとうございました。
どっか間違ってるとこがあったら、ご指摘ください。
それにしても、20問の中にいろんなパターンが含まれていて、よくできてるなあ。
参考:
Standard ECMA-262 3rd Edition -December 1999
JavaScript: new無しで基本型のコンストラクタを呼んだ時の挙動
What is {} + {} in JavaScript?
[ ] == ![ ] の謎を自分でも解いてみた