Javascript 对';瓦特';为CodeMash 2012演讲?
基本上,本文指出了Ruby和JavaScript的一些奇怪之处 我已经在上做了一些结果 下面列出了特定于JavaScript的行为(我不知道Ruby) 我在JSFIDLE中发现我的一些结果与视频中的结果不一致,我不知道为什么。然而,我很想知道JavaScript在每种情况下是如何处理幕后工作的Javascript 对';瓦特';为CodeMash 2012演讲?,javascript,Javascript,基本上,本文指出了Ruby和JavaScript的一些奇怪之处 我已经在上做了一些结果 下面列出了特定于JavaScript的行为(我不知道Ruby) 我在JSFIDLE中发现我的一些结果与视频中的结果不一致,我不知道为什么。然而,我很想知道JavaScript在每种情况下是如何处理幕后工作的 Empty Array + Empty Array [] + [] result: <Empty String> 这与视频的结果相匹配。这是怎么回事?为什么这是一个物体。+操作员做什么 Ob
Empty Array + Empty Array
[] + []
result:
<Empty String>
这与视频的结果相匹配。这是怎么回事?为什么这是一个物体。+
操作员做什么
Object + Empty Array
{} + []
result:
[Object]
这与视频不匹配。视频显示结果为0,而我得到[Object]
Object + Object
{} + {}
result:
[Object][Object]
这与视频也不匹配,输出变量如何产生两个对象?也许我的JSFIDLE是错的
Array(16).join("wat" - 1)
result:
NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
执行wat+1会导致wat1wat1wat1wat1wat1
我怀疑这只是一种简单的行为,尝试从字符串中减去一个数字会导致NaN。以下是对您正在看到(以及应该看到)的结果的解释列表。我使用的参考资料来自
[]+[]
使用加法运算符时,左操作数和右操作数都将首先转换为基本体()。根据,将对象(在本例中为数组)转换为原语将返回其默认值,对于具有有效toString()
方法的对象,该值是调用object.toString()
()的结果。对于数组,这与调用array.join()
()相同。连接一个空数组会产生一个空字符串,因此加法运算符的步骤#7返回两个空字符串的串联,即空字符串[]+{}
与[]+[]
类似,两个操作数都首先转换为原语。对于“对象对象”(§15.2),这也是调用对象.toString()
的结果,对于非空、非未定义的对象,它是“[对象对象]”
(){}+[]
这里的{}
不是作为一个对象来解析的,而是作为一个空块来解析的(至少只要您不强制该语句成为一个表达式,但稍后会详细介绍)。空块的返回值为空,因此该语句的结果与+[]
相同。一元+
运算符()返回ToNumber(ToPrimitive(操作数))
。正如我们已经知道的,ToPrimitive([])
是空字符串,根据,ToNumber(“”)
是0{}+{}
与前一种情况类似,第一个{}
被解析为返回值为空的块。同样,+{{code>与tonnumber(ToPrimitive({}))
,以及ToPrimitive({})
是“[object object]”
(请参见[+{}{code>)。因此,为了得到+{}
的结果,我们必须在字符串“[object object]”
上应用ToNumber
。按照中的步骤操作时,我们得到NaN
,结果是:
如果语法无法将字符串解释为StringNumericLiteral的扩展,则结果为NaN
数组(16)。加入(“wat”-1)
根据和,Array(16)
创建一个长度为16的新数组。要获取要联接的参数值,步骤5和步骤6显示,我们必须使用ToNumber
将两个操作数转换为一个数字ToNumber(1)
仅仅是1(),而ToNumber(“wat”)
同样是NaN
。按照的步骤7,指示
如果任一操作数为NaN,则结果为NaN
因此Array(16.join)的参数是NaN
。根据§15.4.4.5(Array.prototype.join
),我们必须调用参数ToString
,它是“NaN”
():
如果m是NaN,则返回字符串“NaN”
在的第10步之后,我们将重复15次将“NaN”
和空字符串串联在一起,这等于您看到的结果。
当使用“wat”+1
而不是“wat”-1
作为参数时,加法运算符将1
转换为字符串,而不是将“wat”
转换为数字,因此它有效地调用数组(16)。join(“wat1”)
至于为什么在
{}+[]
案例中会看到不同的结果:当将其用作函数参数时,您强制语句成为ExpressionStatement,这使得无法将{}
解析为空块,因此,它被解析为一个空的对象文本。以下是对您正在看到(以及应该看到)的结果的解释列表。我使用的参考资料来自
[]+[]
使用加法运算符时,左操作数和右操作数都将首先转换为基本体()。根据,将对象(在本例中为数组)转换为原语将返回其默认值,对于具有有效toString()
方法的对象,该值是调用object.toString()
()的结果。对于数组,这与调用array.join()
()相同。连接一个空数组会产生一个空字符串,因此加法运算符的步骤#7返回两个空字符串的串联,即空字符串[]+{}
与[]+[]
类似,两个操作数都首先转换为原语。对于“对象对象”(§15.2),这也是调用对象.toString()
的结果,对于非空、非未定义的对象,它是“[对象对象]”
(){}+[]
这里的{}
不是作为对象解析的,而是作为空块(,至少作为l)解析的
Array(16).join("wat" - 1)
result:
NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
var obj = {
valueOf: function () {
console.log("valueOf");
return {}; // not a primitive
},
toString: function () {
console.log("toString");
return {}; // not a primitive
}
}
> Number(obj)
valueOf
toString
TypeError: Cannot convert object to primitive value
if (u)
v;
if (x) {
y;
z;
}
function out(code) {
function format(x) {
return typeof x === "string" ?
JSON.stringify(x) : x;
}
document.writeln('>>> ' + code);
document.writeln(format(eval(code)));
}
document.writeln("<pre>");
out('[] + []');
out('[] + {}');
out('{} + []');
out('{} + {}');
out('Array(16).join("wat" + 1)');
out('Array(16).join("wat - 1")');
out('Array(16).join("wat" - 1) + " Batman!"');
document.writeln("</pre>");
+-----------------+-------------------+---------------+
| Primitive Value | String value | Numeric value |
+-----------------+-------------------+---------------+
| null | “null” | 0 |
| undefined | “undefined” | NaN |
| true | “true” | 1 |
| false | “false” | 0 |
| 123 | “123” | 123 |
| [] | “” | 0 |
| {} | “[object Object]” | NaN |
+-----------------+-------------------+---------------+