前端学习 第一弹: JavaScript关于 对象和原始值以及+ 的知识点
关于原始值的问题
在 JavaScript 中,一共有两种类型的值:
-
原始值(primitives)
-
undefined
-
null
-
boolean
-
number
-
string
-
-
对象值(objects)。
除了原始值外,其他的所有值都是对象类型的值,包括数组(array)和函数(function)。
JavaScript 引擎内部的抽象操作 ToPrimitive()
有着这样的签名:
ToPrimitive(input,PreferredType?)
可选参数 PreferredType
可以是 Number
或者 String
。 它只代表了一个转换的偏好,转换结果不一定必须是这个参数所指的类型(汗),但转换结果一定是一个原始值。
其步骤又如下几步:
1.if input是原始值 return input
2.if input是对象 x=input.valueOf(); if x是原始值 return x;
3.y=x.toString();
if y是原始值 return y
else 抛出 TypeError
异常
通过 ToNumber() 将值转换为数字
下面的表格解释了 ToNumber()
是如何将原始值转换成数字的 (§9.3)。
参数 | 结果 |
---|---|
undefined | NaN |
null | +0 |
boolean | true被转换为1,false转换为+0 |
number | 无需转换 |
string | 由字符串解析为数字。例如,"324"被转换为324 |
如果输入的值是一个对象,则会首先会调用 ToPrimitive(obj, Number)
将该对象转换为原始值, 然后在调用 ToNumber()
将这个原始值转换为数字。
通过ToString()将值转换为字符串
下面的表格解释了 ToString()
是如何将原始值转换成字符串的(§9.8)。
参数 | 结果 |
---|---|
undefined | "undefined" |
null | "null" |
boolean | "true" 或者 "false" |
number | 数字作为字符串。比如,"1.765" |
string | 无需转换 |
如果输入的值是一个对象,则会首先会调用 ToPrimitive(obj, String)
将该对象转换为原始值, 然后再调用 ToString()
将这个原始值转换为字符串。
那么为什么 (1+{})[4]='j' ?往下看
二元加法运算
在js中 value1 + value2 又如下的计算步骤
-
将两个操作数转换为原始值 (以下是数学表示法的伪代码,不是可以运行的 JavaScript 代码):
javascript prim1 := ToPrimitive(value1) prim2 := ToPrimitive(value2)
PreferredType
被省略,因此Date
类型的值采用String
,其他类型的值采用Number
。 -
如果 prim1 或者 prim2 中的任意一个为字符串,则将另外一个也转换成字符串,然后返回两个字符串连接操作后的结果。
-
否则,将 prim1 和 prim2 都转换为数字类型,返回他们的和。
所以根据以上内容有一下结论:
[]+{}='[object Object]'
1+{}='1[object Object]'(1+{})[4]='j'
arr=[]; arr.valueOf()===arr = true;
1+{valueOf : function(){ return 2;}} = 3
'abc' + {toString : function(){ return 'def'}} = 'abcdef'
[]+[]=''
[1,2]+[3,4]='1,23,4'
一元运算符 +
当我们按照上面的二元+来计算到 {}+{}会惊奇的发现结果等于 NaN !
其实这里使用的是一元运算 +value 将value转化为数字 和Number()效果一样。
所以
+"213"=213
+[]=0
{}+{}=NaN;
({}+{})='[object Object][object Object]'
但是不同的引擎对于{}+[]结果并不相同
chrome&firefox : {}+[]=0
Node.js: {}+[]=''
所以我们来看为什么++[[]][+[]]+[+[]] = '10'
++[[]][+[]]+[+[]]
1step. ++[[]][0]+[0] (这里[[]][0]是[[]]数组的第一个元素也就是[] )
2step. ++[]+'0' (++[]等效于+([]+1)=+(''+1)=+('1')=1)
3step. 1+'0' ==='10'
补充js中连接对象和数组的方法
[1, 2].concat([3, 4])
[1, 2, 3, 4]
> var o1 = {eeny:1, meeny:2};
> var o2 = {miny:3, moe: 4};
> _.extend(o1, o2)
{eeny: 1, meeny: 2, miny: 3, moe: 4}
不过需要注意的是concat中[1,2]并未改变,而.extend方法中o1={eeny :1, meeny:2, miny:3, moe:4} o2不变