JS中的值有两种类型:原始类型(Primitive)、对象类型(Object)。原始类型包括:Undefined、Null、Boolean、Number和String等五种。这两大类别的数据存储方式是不同的。javascript
存储空间的时空关系能够归纳为空间大,访问起来就慢,反之亦然。堆比栈大,栈比堆的运算速度快,html
对象是一个复杂的结构,而且能够自由扩展,如:数组能够无限扩充,对象能够自由添加属性。将它们放在堆中是为了避免影响栈的效率。而是经过引用的方式查找到堆中的实际对象再进行操做。java
相对于对象类型而言,原始类型就比较稳定,而且它只占据很小的内存。不将原始类型放在堆是由于经过引用到堆中查找实际对象是要花费时间的,而这个综合成本远大于直接从栈中取得实际值的成本。因此简单数据类型的值直接存放在栈中。`数组
假如你打算把一个变量赋予对象类型的值,可是如今尚未赋值,那么你能够用null表示此时的状态(证据之一就是typeof null 的结果是'object');相反,假如你打算把一个变量赋予原始类型的值,可是如今尚未赋值,那么你能够用undefined表示此时的状态。ui
==运算规则的准备描述以下:spa
看完以后有没有感受有点脑袋疼,这样的描述很难让人在实践中使用,因此颇有必要对上述规则进行简化归纳:3d
undefined == null,结果是true。且它俩与全部其余值比较的结果都是false。code
String == Boolean,须要两个操做数同时转为Number。htm
String/Boolean == Number,须要String/Boolean转为Number。对象
Object == Primitive,须要Object转为Primitive(具体经过valueOf和toString方法)。
那么Boolean,Number,Primitive的转换规则是:
(1)其它类型转换成Boolean的规则是:
(2)其它类型转换成Number类型的规则
object类型通常要先转换成string类型,接着才进行Number类型的转换。字符串转化为数字的规则规范中描述得很复杂,可是大体说来,就是把字符串两边的空白字符去掉,而后把两边的引号去掉,看它可否组成一个合法的数字。若是是,转化结果就是这个数字;不然,结果是NaN。
Number('123') // 结果123 Number('1.2e3') // 结果1200 Number('123abc') // 结果NaN Number('\r\n\t123\v\f') // 结果123
固然也有例外,好比空白字符串转化为数字的结果是0。即:
Number('') // 结果0 Number('\r\n\t \v\f') // 结果0
须要补充说明的是:
(3)对象类型向primitive类型转换的规则是:
为何要区分原始类型和复杂类型?
原始类型是一种单纯的类型,它们直接了当、容易理解。然而缺点是表达能力有限,难以扩展,因此就有了对象。对象是属性的集合,而属性自己又能够是对象。因此对象能够被构造得任意复杂,足以表示各类各样的事物。
可是,有时候事情复杂了也不是好事。好比一篇冗长的论文,并非每一个人都有时间、有耐心或有必要从头至尾读一遍,一般只了解其中心思想就够了。因而论文就有了关键字、概述。JavaScript中的对象也同样,咱们须要有一种手段了解它的主要特征,因而对象就有了toString()和valueOf()方法。
这两种方法的区别是:
toString()方法用来获得对象的一段文字描述;而valueOf()方法用来获得对象的特征值。
toString()方法倾向于返回一个字符串。valueOf()方法倾向于返回一个数字——尽管内置类型中,valueOf()方法返回数字的只有Number和Date。
对于全部非日期对象来讲,对象到原始值的转换基本上是对象到数字的转换
通常来讲,对象到数字的转换通过了以下过程:
1.若是对象具备valueOf()方法,后者返回一个原始值,则js将这个原始值转换成数字,并返回这个数字。
2.不然,若是对象具备toString()方法,后者返回一个原始值,则js将转换并返回。(首先js转换成相应的字符串原始值,再继续将这个原始值转换成相应的数字类型,再返回数字)
3.不然,js抛出一个类型错误异常。
通常来讲,对象到字符串的转换通过了以下步骤:
1.若是对象具备toString()方法,则调用这个方法。若是它返回一个原始值,js将这个值转换成字符串,并返还这个字符串结果。
2.若是对象没有toString()方法,或者toString并不返回一个原始值,那么js将调用valueOf()方法。
3.不然,js没法从toString()或者valueOf()得到一个原始值,所以这时它将抛出一个类型错误异常。
下图第一列和第二列是其它类型调用toString方法时的转换规则

须要说明的是: toString方法会将{}转换成"[object Object]",将function(){}转换成"function(){}"
其它类型调用valueOf方法的转换规则是:

通过层层深刻剖析,如今你应该理解前面各类数据类型进行 == 运算时的隐式运做规则了吧。如今再碰到以下的问题,是否是感受思路很清晰
[]==[] //false []==![] //true {}==!{} //false 实际上被解析成 { ' } == !{ ' } {}==![] //Uncaught SyntaxError: Unexpected token == 表达式不能以{开头 {}是个语句块,后面跟== ![]就变成了一种语法错误的语句块
// 在语法解析的时候,若是一个语句以「{」开头,就只把它解释成语句块。换用形式语法的说法,就是「表达式语句不能以『{』开头」。对表达式语句开头的另外一个限制——限制「function」出如今开头——同理。 ![]=={} //false []==!{} //true undefined==null //true
一张图完全搞懂JavaScript的==运算 [] == [] // false 由于它们的引用地址不同
由上面的比较能够得出:
对任何一种类型进行取反 会获得一个boolean类型的值
[]在与不一样的类型对比的时候,会转换成0
{}在与不一样的类型对比的时候,会转换成NaN,
不一样类型的比较最终都被转换成number类型的比较
参考文章
[1]