博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript中的 ==
阅读量:6682 次
发布时间:2019-06-25

本文共 4990 字,大约阅读时间需要 16 分钟。

hot3.png

本文所有代码都在 node v0.10.28 中测试通过,因为node用的也是v8的javascript引擎,所以理论上来说在chrome中的表现应该一致,其它引擎各位可以自己测试

准备工作

我们先定义一个对象来进行比较

1
2
3
function foo() {
  
this
.name =
"foo"
;
}

再定义一个函数来比对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function compare(f) {
  
console.log(
"\ncompare with number:"
);
  
console.log(
"number f == 1: %s"
, f ==
1
);
  
console.log(
"number f == 0: %s"
, f ==
0
);
 
  
console.log(
"\ncompare with string:"
);
  
console.log(
"string f == \"\" : %s"
, f ==
""
);
  
console.log(
"string f == \"foo\" : %s"
, f ==
"foo"
);
 
  
console.log(
"\ncompare with boolean:"
);
  
console.log(
"boolean f == true : %s"
, f ==
true
);
  
console.log(
"boolean f == false : %s"
, f ==
false
);
 
  
console.log(
"\ncompare with object:"
);
  
console.log(
"object f == {} : %s"
, f == {});
}

第一次比较

1
compare(
new
foo());

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
compare with number:
number f ==
1
:
false
number f ==
0
:
false
 
compare with string:
string f ==
""
:
false
string f ==
"foo"
:
false
 
compare with
boolean
:
boolean
f ==
true
:
false
boolean
f ==
false
:
false
 
compare with object:
object f == {} :
false

这个结果大家基本上都能理解

第二次比较

这次我们给这个对象添加一个方法 valueOf 然后再来进行比较看看

1
2
3
foo.prototype.valueOf  = function() {
    
return
0
;
};

1
compare(
new
foo());

结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
compare with number:
number f ==
1
:
false
number f ==
0
:
true
 
compare with string:
string f ==
""
:
true
string f ==
"foo"
:
false
 
compare with
boolean
:
boolean
f ==
true
:
false
boolean
f ==
false
:
true
 
compare with object:
object f == {} :
false

这个结果我们发现

  • 和 0 比较

  • 和空字符串比较

  • 和false比较

这三种情况返回 true

这个结果让人不好理解

我们在valueOf方法中加入一些输出再来看看

1
2
3
4
foo.prototype.valueOf  = function() {
  
console.log(
'valueOf: '
+
this
.name);
  
return
0
;
};

1
compare(
new
foo());

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
compare with number:
valueOf: foo
number f ==
1
:
false
valueOf: foo
number f ==
0
:
true
 
compare with string:
valueOf: foo
string f ==
""
:
true
valueOf: foo
string f ==
"foo"
:
false
 
compare with
boolean
:
valueOf: foo
boolean
f ==
true
:
false
valueOf: foo
boolean
f ==
false
:
true
 
compare with object:
object f == {} :
false

现在我们可以猜测一下了, javascript在进行对象和基本数据类型(暂且把string也当做一种基本数据类型,下面说基本数据类型的时候也会带上string)比较的时候,会调用对象的valueOf方法的返回值来进行比较.

这样就可以解释number比较中为什么和0比较是true了,

但是还有和空字符串比较是true,和false比较是true,这里我的理解是 javascript在数字和字符串以及boolean进行比较的时候,会转换成数字后进行比较,所以 0 == ""0 == false也是true

只有最后一个和对象比较的时候没有打印 valueOf: foo 所以也可以认为是对象比较时,只比较引用地址,理论上来说,对象比较 == 和 === 应该是一样的,例如如下代码:

1
2
3
4
5
var b1 =
new
Boolean(
false
);
var b2 =
new
Boolean(
false
);
 
console.log(b1 == b2);
console.log(b1 === b2);

输出两次false

第三次比较

这次我们将valueOf方法再修改一下,返回不是基本数据类型试一下,就返回自己吧

1
2
3
4
foo.prototype.valueOf  = function() {
    
console.log(
'valueOf: '
+
this
.name);
    
return
this
;
};

1
compare(
new
foo());

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
compare with number:
valueOf: foo
number f ==
1
:
false
valueOf: foo
number f ==
0
:
false
 
compare with string:
valueOf: foo
string f ==
""
:
false
valueOf: foo
string f ==
"foo"
:
false
 
compare with
boolean
:
valueOf: foo
boolean
f ==
true
:
false
valueOf: foo
boolean
f ==
false
:
false
 
compare with object:
object f == {} :
false

这次和第一次比较没什么出入,只是打印了一些方法调用日志而已,结果也理所当然的应该这样了.

但是javascript为什么没有递归调用我们的valueOf方法呢,按道理我们返回了自己,然后它进行比较的时候应该再次调用valueOf

这次我们再加入一个toString方法来看看

1
2
3
4
foo.prototype.toString = function(){
    
console.log(
this
.name +
" : toString"
);
    
return
this
.name;
}

1
compare(
new
foo());

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
compare with number:
valueOf: foo
foo : toString
number f ==
1
:
false
valueOf: foo
foo : toString
number f ==
0
:
false
 
compare with string:
valueOf: foo
foo : toString
string f ==
""
:
false
valueOf: foo
foo : toString
string f ==
"foo"
:
true
 
compare with
boolean
:
valueOf: foo
foo : toString
boolean
f ==
true
:
false
valueOf: foo
foo : toString
boolean
f ==
false
:
false
 
compare with object:
object f == {} :
false

我们发现每次输出valueOf的后面都跟随了一个toString的调用.

也就是说 javascript在调用valueOf后发现不是基本数据类型的时候,会调用toString的返回值再来进行比较

和我们观测到的结果一致,只有 f== "foo" 的结果是true

这样也可以解释为什么没有递归调用我们的valueOf方法了

接下来我们再狠一点,toString我们也返回自己,看看javascript会怎么处理

第四次比较

修改toString方法为:

1
2
3
4
foo.prototype.toString = function(){
    
console.log(
this
.name +
" : toString"
);
    
return
this
;
}

1
compare(
new
foo());

这次的结果会在意料之外的:

结果为:

1
2
3
4
5
6
7
8
9
10
11
12
console.log(
"number f == 1: %s"
, f ==
1
);
                                     
^
TypeError: Cannot convert object to primitive value
    
at compare (/home/
0x0001
/Desktop/test.js:
25
:
38
)
    
at Object.<anonymous> (/home/
0x0001
/Desktop/test.js:
41
:
1
)
    
at Module._compile (module.js:
456
:
26
)
    
at Object.Module._extensions..js (module.js:
474
:
10
)
    
at Module.load (module.js:
356
:
32
)
    
at Function.Module._load (module.js:
312
:
12
)
    
at Function.Module.runMain (module.js:
497
:
10
)
    
at startup (node.js:
119
:
16
)
    
at node.js:
906
:
3

结果报异常了

最后我觉得,javascript在将对象和基本数据类型进行比较的时候,会先调用valueOf的返回值来进行比较,如果valueOf返回的不是基本数据类型,那么继续调用toString方法的返回值来进行比较,

如果toString的返回值还不是基本数据类型,那么就无法比较了

转载于:https://my.oschina.net/u/1866497/blog/300202

你可能感兴趣的文章
Nagios整合pnp绘制性能分析图表
查看>>
fms 安装问题及yum问题
查看>>
DEDECMS 另类入侵
查看>>
Exchange server 2010系列教程之一 安装Exchange 2010准备条件
查看>>
Citrix XenServer 6.5 加入 Windows AD 域控环境中
查看>>
Nginx反向代理与负载均衡:节点服务器单/多虚拟机配置+实验环境搭建+原理解析...
查看>>
网络管理之局域网协议设置一点通
查看>>
Linux最大文件打开数使用经验详解
查看>>
搜索助理、意外错误、操作无法完成解决方法
查看>>
Qt的QLabel小用
查看>>
nginx 根据IP 进行灰度发布
查看>>
关于cacti图形显示不正常的解决办法
查看>>
使用Configuration Manager配置报表服务
查看>>
DHCP服务的配置与管理(1)DHCP协议原理
查看>>
Python 学习笔记 - 反射
查看>>
组策略实现对IE受信任站点添加
查看>>
zabbix proxy搭建及应用proxy监控腾讯CVM服务器
查看>>
机器学习入门|聚类(一)
查看>>
一步一步学Silverlight 2系列(24):与浏览器交互相关辅助方法
查看>>
在cocos2d-x中编译/调试curl库
查看>>