加号根据语境有三个用途:
1.取正
2.加法
3.连接字符串
当作为 “取正” 运算符时,会对非数字做一个隐式的数字转换。
转换规则如下:
true转换为1,false转换为0
null转换为0
undefined转换为NaN
空字符串转换为0
对象会调用valueOf()方法,如果该方法返回的是基本类型并且非数字,则按照上面的4种规则继续转换,如果返回的是对象类型,则会调用toString()方法,如果toString()方法返回的是基本类型并且非数字,则也按照上面的4种规则进行转换,如果toString()返回的也是一个对象,则转换失败,会引发错误。
知道上面的转换规则后,我们再来分析这个表达式:
+[] 最终会转换为 0,为什么呢? 因为它的转换步骤是这样的,+[]中的加号此时是取正运算符,这意味着后面的运算数要被隐式的转换成一个数字,之前我们说过如果这个运算数是个对象的话,就会先调用它的valueOf()方法,我们发现对数组[]调用valueOf()方法,所返回的仍然是个对象,所以继续会调用[]的toString()方法,此时toString()方法返回一个空字符串,按照上面的转换规则,空字符串最终会被转换为0,所以+[]的最终运算结果是0
搞懂了+[]是如何运算的,相信下面的表达式就很容易理解了:
++[[]][+[]] 简化后变成 ++[[]][0]
++[[]][0] 简化后变成 ++[]
最终复杂的 ++[[]][+[]] 变成了 ++[]
++[]会将数组转化为数字0,然后执行加1操作,所以运算结果是1.
在来看看我们那复杂的表达式简化成了这样:
1 +[+[]] = 10 ?
继续简化
1 +[0] = 10 ?
此时此刻已经很简单了吧? 呵呵,注意,这个时候的加号要变换角色了啊,因为这里是数字和对象相加,所以会先调用对象的valueOf()方法,我表达能力很差,所以就用伪代码了啊,请看:
var ret = 对象.valueOf();
if( ret 是基本类型 ){
if( ret 是字符串类型 ) {
执行字符串连接运算
}
// true、false、NaN、undefined、number
else{
执行加法运算
}
}
//ret是个对象
else{
ret = 对象.toString();
if( ret 是基本类型 ){
if( ret 是字符串类型 ) {
执行字符串连接运算
}
// true、false、NaN、undefined、number
else{
执行加法运算
}
}
//ret是个对象
else{
报错;
}
}
所以最终的表达式,变成了 1+0(这个0是字符串) = 10
1.取正
2.加法
3.连接字符串
当作为 “取正” 运算符时,会对非数字做一个隐式的数字转换。
转换规则如下:
true转换为1,false转换为0
null转换为0
undefined转换为NaN
空字符串转换为0
对象会调用valueOf()方法,如果该方法返回的是基本类型并且非数字,则按照上面的4种规则继续转换,如果返回的是对象类型,则会调用toString()方法,如果toString()方法返回的是基本类型并且非数字,则也按照上面的4种规则进行转换,如果toString()返回的也是一个对象,则转换失败,会引发错误。
知道上面的转换规则后,我们再来分析这个表达式:
+[] 最终会转换为 0,为什么呢? 因为它的转换步骤是这样的,+[]中的加号此时是取正运算符,这意味着后面的运算数要被隐式的转换成一个数字,之前我们说过如果这个运算数是个对象的话,就会先调用它的valueOf()方法,我们发现对数组[]调用valueOf()方法,所返回的仍然是个对象,所以继续会调用[]的toString()方法,此时toString()方法返回一个空字符串,按照上面的转换规则,空字符串最终会被转换为0,所以+[]的最终运算结果是0
搞懂了+[]是如何运算的,相信下面的表达式就很容易理解了:
++[[]][+[]] 简化后变成 ++[[]][0]
++[[]][0] 简化后变成 ++[]
最终复杂的 ++[[]][+[]] 变成了 ++[]
++[]会将数组转化为数字0,然后执行加1操作,所以运算结果是1.
在来看看我们那复杂的表达式简化成了这样:
1 +[+[]] = 10 ?
继续简化
1 +[0] = 10 ?
此时此刻已经很简单了吧? 呵呵,注意,这个时候的加号要变换角色了啊,因为这里是数字和对象相加,所以会先调用对象的valueOf()方法,我表达能力很差,所以就用伪代码了啊,请看:
var ret = 对象.valueOf();
if( ret 是基本类型 ){
if( ret 是字符串类型 ) {
执行字符串连接运算
}
// true、false、NaN、undefined、number
else{
执行加法运算
}
}
//ret是个对象
else{
ret = 对象.toString();
if( ret 是基本类型 ){
if( ret 是字符串类型 ) {
执行字符串连接运算
}
// true、false、NaN、undefined、number
else{
执行加法运算
}
}
//ret是个对象
else{
报错;
}
}
所以最终的表达式,变成了 1+0(这个0是字符串) = 10