参考下面用Javascript编写的代码。
let a = {
value: 2,
toString: function() {
return ++this.value;
}
}
if (a == 3 && a == 4) {
console.log('Condition is true');
}

输出为"Condition is true"
。看起来它调用toString()
函数。但是如何?
当我用"=="
替换"==="
时,条件不会计算为true,这次不会调用toString()
函数吗?
有人可以详细解释我的内容吗?
答案 0 :(得分:1)
输出为“条件为真”。看起来它调用'toString()' 功能
每当您在具有不同类型的两个变量之间使用==
运算符时,将在内部调用toString
方法,该方法将强制转换一个member
。看看type coercion
但是怎么样?
您正在为toString
对象创建一个自定义a
函数,该函数会在每次使用时更改它返回的内容,以使其满足所有两个条件。
您也可以使用valueOf
方法。
===
运营商怎么样?
否则,===
运算符不会转换。
这意味着什么?
如果您使用===
运算符,其中两个值不同,类型为===
,则只返回 false 。
答案 1 :(得分:1)
执行==
时,这不是一个严格的比较,因此它对条件a == 3 && a == 4
的作用是首先比较a == 3
。因为,它不是严格的比较,它会将a
更改为字符串。由于toString()
中有a
,因此会将a
的值从2增加到3,因此a == 3
会导致true
。然后,a == 4
检查方式相同,这次a
的值为3
,因此当它检查a == 4
时,通过调用{true
会产生toString()
{1}} a
的功能。
let a = {
value: 2,
toString: function() {
return ++this.value;
}
}
if (a == 3 && a == 4) {
console.log('Condition is true');
}
但是,当您使用===
时,它可以作为严格比较,LHS的类型应该与RHS匹配。因此,a
是LHS中的一个对象,RHS中有一个数字类型,因此false
的结果为a == 3
,因此a == 3 && a == 4
let a = {
value: 2,
toString: function() {
return ++this.value;
}
}
if (a === 3 && a === 4) {
console.log('Condition is true');
} else {
console.log('Condition is false');
}
答案 2 :(得分:0)
除了Mihai的回答,===
是一个严格的类型检查等式运算符,它检查操作数的类型和值。
在您的情况下,a
的类型是对象,而3
和4
是数字。因此,条件不会评估为true
。
答案 3 :(得分:0)
当你使用==时,它会检查对象是否有假值。这就是为什么你从== 4和= = 3得到真实。看看类型强制。它在比较它们时不会强制变量,这就是为什么你不能进入块语句
答案 4 :(得分:0)
您可以找到有关' =='的详细信息。和' ==='适用于以下链接的javascript: Equality comparisons and sameness
在此网址中,使用=='参考'松散平等部分。
在您的情况下,您的比较为== 3. a是对象,3是数字。因此,比较将发生在ToPrimitive(a)== 3. ToPrimitive(a)做的是尝试在A上调用a.toString和a.valueOf方法的不同序列。这就是你的toString函数的调用方式。
答案 5 :(得分:0)
从表面上看,您的问题看起来就像==
和===
运营商之间的绝对差异,但实际上还有更多内容。
对于您的第一个问题,由于javascript是不是严格类型的语言,因此有2个运算符,==
会尽可能将左操作数转换为右操作数而{{1}如果类型不同,===
。
更有趣的问题是调用NaN
方法时。通常,当您通过键入对象文字或通过构造函数创建对象时,它将从Object继承toString
,您可以轻松地检查:
toString
现在您可能忘记的是还有var u = function(){};
var w = {};
u.prototype.toString === Object.prototype.toString //true
w.toString === Object.prototype.toString //true as well
方法:
valueOf
但是它做了什么?我指出了自己:
u.prototype.valueOf === Object.prototype.valueOf //true
w.valueOf === Object.prototype.valueOf //true as well
因此,当给出一个对象时,第一个选择是使用w.valueOf === w //true
u.prototype.valueOf() === u.prototype //true as well
becuae toString
将导致对象本身。 valueOf
默认提供什么?它可以取决于其原型链上的内容:
toString
因此,默认情况下,首选是使用对象的最近w.toString() //"[object Object]"
u.toString() //"function (){}"
u.prototype.toString.call(u) //"[object Function]"
方法。现在看看如果我们覆盖 BOTH toString
和valueOf
会发生什么,让我构建这个对象:
toString
此对象将保留“分类帐”,即在类型转换期间调用的 var x = {
inner:10,
ledger:[],
result:[],
timeout:0,
toString:function(){
console.log("String");
clearTimeout(this.timeout);
this.timeout = setTimeout((function(){
this.result = this.ledger;
this.ledger = []}).bind(this)
,0) ;
this.ledger.push("toString");
this.ledger.slice(-2);
return String(this.inner);
},
valueOf:function(){
console.log("Valueof");
clearTimeout(this.timeout);
this.timeout = setTimeout((function(){
this.result = this.ledger;
this.ledger = []}).bind(this)
,0) ;
this.ledger.push("valueOf");
this.ledger.slice(-2);
return this.inner;
}
}
或valueOf
或两者的数组。它也将toString
。因此,以下是一些将触发类型转换的操作,就像console.log
:
==
因此,在许多情况下,如果找到使用的非默认值。如果右操作数是字符串,则 +x //10
//ValueOf
"5" + x //"510"
//ValueOf
x + [] //10
//ValueOf
x + "str"//"10str"
//ValueOf
x.toString() //"10"
//String
String(x) //"10"
//String
x + {u:""} //"10[object Object]"
//valueOf
的返回值将转换为字符串而不是对象上的valueOf
。要覆盖默认行为,您可以使用toString
或toString
强制调用字符串,如示例所示。所以优先级列表如下:
自定义值>>自定义toString>>默认为toString>>>>默认值
答案 6 :(得分:0)
碰巧注意到toString
是在插值字符串中调用的,它的执行优先于valueOf
var a = {
value: 1000,
toString: () => 'call toString method',
valueOf: () => 'call valueOf method'
};
console.log(`interpreted value: ${a}`); // interpreted value: call toString method