a + b:
pa = ToPrimitive(a)
pb = ToPrimitive(b)
if(pa is string || pb is string)
return concat(ToString(pa),ToString(pb))
else
return add(ToNumber(pa),ToNumber(pb))</code></pre>
JS对于Object与Array的设计
在JS中所设计的Object纯对象类型的valueOf与toString方法,它们的返回如下:
valueOf方法返回值: 对象本身。(所以ToPrimitive最后要返回toString的值了
)
toString方法返回值: "[object Object]"字符串值,不同的内建对象的返回值是"[object type]"字符串,"type"指的是对象本身的类型识别,例如Math对象是返回"[object Math]"字符串。但有些内建对象因为覆盖了这个方法,所以直接调用时不是这种值。(注意: 这个返回字符串的前面的"object"开头英文是小写,后面开头英文是大写)
一元正号(+),具有让首选类型(也就是hint)设置为数字(Number)的功能,所以可以强制让对象转为数字类型,一般的对象会转为:
这里首选类型其实本身就是数字,+让toString输出的字符串再强转了一次。
> +{} //相当于 +"[object Object]"
NaN
当然,对象的这两个方法都可以被覆盖,你可以用下面的代码来观察这两个方法的运行顺序,下面这个都是先调用valueOf的情况:
let obj = {
valueOf: function () {
console.log('valueOf');
return {}; // object
},toString: function () {
console.log('toString');
return 'obj'; // string
}
}
console.log(1 + obj); //valueOf -> toString -> '1obj'
console.log(+obj); //valueOf -> toString -> NaN
console.log('' + obj); //valueOf -> toString -> 'obj'
实例
基本类型间运算
> '1' + 123
"1123"
'1' + false
"1false"
'1' + null
"1null"
'1' + undefined
"1undefined"
> 1 + true //true转为1,false转为0
2
1 + null //null转为0
1
1 + undefined //null转为NaN
NaN
> true + true
2
true + null
1
undefined + null
NaN
对象类型间运算
> [] + []
""
两个数组相加,依然按照valueOf -> toString的顺序,但因为valueOf是数组本身,所以会以toString的返回值才是原始数据类型,也就是空字符串,所以这个运算相当于两个空字符串在相加,依照加法运算规则第2步骤,是字符串连接运算(concatenation),两个空字符串连接最后得出一个空字符串。
特别注意: {} + {}在不同的浏览器有不同结果
如果在第一个(前面)的空对象加上圆括号(()),这样JS就会认为前面是个对象,就可以得出同样的结果:
> ({}) + {}
"[object Object][object Object]"
注: 上面说的行为这与加号运算的第一个(前面)的对象字面值是不是个空对象无关,就算是里面有值的对象字面,例如{a:1,b:2},也是同样的结果
。
> 1 + (new Date())
"1Sun Nov 27 2016 01:09:03 GMT+0800 (CST)"
要得出Date对象中的valueOf返回值,需要使用一元加号(+),来强制转换它为数字类型,例如以下的代码:
> +new Date()
1480180751492
> 1-'1'
0
1+'1'
'11'
总结
解构赋值产生的问题
> {name: 1}['name'] = '2'
{name: 1}['name'] = '2'
^^^^^^
SyntaxError: Invalid destructuring assignment target
上述错误。
> {name: 1}[name] = '2'
'2'
{name: 1}[name]相当于{name: 1};[name]。解构赋值成功。
{}问题
> var name = 'test'
{[name]:1}
Object {1: 1}
{[name]:1};[name] = '1'
VM174:1 Uncaught SyntaxError: Unexpected token :
上述错误其实是由于,{[name]:1}中{}是表达式,返回对象;{[name]:1};[name] = '1'中{}是语句,语句中不允许”[name]:1“,换而言之语句中允许”{name: 1}"写法。
{} + {}
{} + {}的结果是会因浏览器而有不同结果,Chrome(v55)中是object Object字符串连接,但其它的浏览器则是认为相当于+{}运算,得出NaN数字类型。
{} + []的结果是相当于+[],结果是0数字类型。
Date对象
Date对象上面有提及是首选类型为"字符串"的一种异常的对象,这与其他的对象的行为不同(一般对象会先调用valueOf再调用toString),在进行加号运算时时,它会优先使用toString来进行转换,最后必定是字符串连接运算(concatenation)
> 1 + (new Date())
"1Sun Nov 27 2016 01:09:03 GMT+0800 (CST)"
toString()
Object.prototype.toString()才是用来检测变量本身的类型,typeof是检测基本类型,instanceof是检测是否在原型链上。(注意一下Object.prototype.toString与Number.prototype.toString、Array.prototype.toString不同)
> var a = 1
undefined
a.toString()
'1'
Number.prototype.toString.call(a)
'1'
Object.prototype.toString.call([1,2])
'[object Array]'
Array.prototype.toString.call([1,2])
'1,2'
[1,2].join()
'1,2'
toString方法返回值: "[object Object]"字符串值,不同的内建对象的返回值是"[object type]"字符串,"type"指的是对象本身的类型识别,例如Math对象是返回"[object Math]"字符串。但有些内建对象因为覆盖了这个方法,所以直接调用时不是这种值。(注意: 这个返回字符串的前面的"object"开头英文是小写,后面开头英文是大写。
> Object.prototype.toString.call(null)
'[object Null]'
typeof null
'object'
Object.prototype.toString.call(1)
'[object Number]'
Number()、String()与Boolean()
常被搞混的是直接使用Number()、String()与Boolean()三个强制转换函数的用法,这与包装对象的用法不同,包装对象是必须使用new关键字进行对象实例化的,例如new Number(123),而Number('123')则是强制转换其他类型为数字类型的函数。
基本运算过程
基本运算发生时 => 就需要变量转化成基本类型 => 就需要依据基本类型间运算优先法则统一转化成一类基本类型 => 运算
null undefined
> null + 1 + ''
'1'
null + '' + 1
'null1'
undefined + '' + 1
'undefined1'
undefined + 1 + ''
'NaN'
> undefined == 0
false
null == 0
false
null == undefined
true
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!