JavaScript ==原理与分析


JavaScript原始类型

ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String。

typeof 运算符

typeof 运算符有一个参数,即要检查的变量或值。例如:

var sTemp = "test string";
alert (typeof sTemp);    //输出 "string"
alert (typeof 86);    //输出 "number"

对变量或值调用 typeof 运算符将返回下列值之一:

  • undefined - 如果变量是 Undefined 类型的

  • boolean - 如果变量是 Boolean 类型的

  • number - 如果变量是 Number 类型的

  • string - 如果变量是 String 类型的

  • object - 如果变量是一种引用类型或 Null 类型的

注释:您也许会问,为什么 typeof 运算符对于 null 值会返回 "Object"。这实际上是 JavaScript 最初实现中的一个错误,然后被 ECMAScript 沿用了。现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。

JavaScript引用类型

对于引用类型,众说纷纭。

从网络上总结的暂时有Object、Boolean、Number、String、Date、Array、Function。

==核心原理

知乎大佬manxisuo对于原理进行的全面解析,核心就是类型转换。

先说转换结果:

  • undefined == null,结果是true。且它俩与所有其他值比较的结果都是false。

  • String == Boolean,需要两个操作数同时转为Number。

  • String/Boolean == Number,需要String/Boolean转为Number。

  • Object == Primitive,需要Object转为Primitive(具体通过valueOf和toString方法)。

核心关注引用类型Object转换原始类型(primitive type)

引用类型中的valueOf与toString方法,可以进行重写,类似如下

var obj = {valueOf: function(){ return {} }, toString: function(){ return {}}}

console.log(obj);
console.log(obj.toString());
console.log(obj.valueOf());
console.log(typeof obj);

{valueOf: ?, toString: ?}
{}
{}
object

对于上方obj通过valueOf与toString方法后,最后获得结果为{},而{}这个结果是无法转换为原始类型的。

对象类型转换

ToPrimitive

JavaScript引擎内部的抽象操作ToPrimitive()有着这样的签名:

ToPrimitive(input, PreferredType?)

可选参数PreferredType可以是Number或者String,它只代表了一个转换的偏好,转换结果不一定必须是这个参数所指的类型,但转换结果一定是一个原始值.如果PreferredType被标志为Number,则会进行下面的操作来转换输入的值 (§9.1):

  1. 如果输入的值已经是个原始值,则直接返回它.
  2. 否则,如果输入的值是一个对象.则调用该对象的valueOf()方法.如果valueOf()方法的返回值是一个原始值,则返回这个原始值.
  3. 否则,调用这个对象的toString()方法.如果toString()方法的返回值是一个原始值,则返回这个原始值.
  4. 否则,抛出TypeError异常.

valueOf()转换表

返回值
Array 数组的元素被转换为字符串,这些字符串由逗号分隔,连接在一起。其操作与 Array.toString 和 Array.join方法相同。
Boolean Boolean 值。
Date 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。
Function 函数本身。
Number 数字值。
Object 对象本身。这是默认情况。
String 字符串值。

toString()转换表

操作
Array 将 Array 的元素转换为字符串。结果字符串由逗号分隔,且连接起来。
Boolean 如果 Boolean 值是 true,则返回 “true”。否则,返回 “false”。
Date 返回日期的文字表示法。
Error 返回一个包含相关错误消息的字符串。
Function 返回如下格式的字符串,其中 functionname 是被调用 toString 方法函数的名称:function functionname( ) { [native code] }
Number 返回数字的文字表示。
String 返回 String 对象的值。
默认 返回 “[object objectname]”,其中 objectname 是对象类型的名称。

例子

重写toString()方法

var obj = {};
console.log('result:' + obj);
console.log(obj);
console.log(obj.toString());
console.log(typeof obj);

var tos = {
    a: 'A',
    toString: function () {
        return 'abc';
    }
}
console.log('result:' + tos);
console.log(tos);
console.log(tos.toString());
console.log(typeof tos);

结果:
result:[object Object]
{}
[object Object]
object

result:abc
{a: 'A', toString: ?}
abc
object

{} == null?

// ToPrimitive({}) => {}.valueOf() => {}.toString() => [object Object] => Number( [object Object] ) => NaN
// null => Number(null) => 0
{} == null // false

[''] == '' ?

// ToPrimitive(['']) => [''].valueOf() => [''].toString() => '' => Number( '' ) => 0
// '' => Number('') => 0
[''] == '' // true

总结

知乎大佬Belleve、知乎大佬manxisuo进行了如下总结。

转换总结

双等比较

全等比较

完整比较

  • 红色:===
  • 橙色:==
  • 黄色:<= 和 >= 同时成立,== 不成立
  • 蓝色:只有 >=
  • 绿色:只有 <=

巨人的肩膀

一张图彻底搞懂JavaScript的==运算 - 知乎 (zhihu.com)

(79 条消息) Javascript 中 == 和 === 区别是什么? - 知乎 (zhihu.com)

ECMAScript 原始类型 (w3school.com.cn)

ECMAScript 引用类型 (w3school.com.cn)

JS输出内容为[object Object] - 简书 (jianshu.com)