11

编码:

var num = 20;

if(num == "20")
{
    alert("It works");
}
else
{
    alert("Not working");
}

问题:

  1. 在 C 编程中,我们有一个规则名称数据类型提升,当数据类型混合时(例如:整数和浮点数的加法),在执行加法之前,整数将首先转换为浮点数。

  2. 上面的代码将提示我一个警告框,"It works"其中显示if测试条件评估为真的消息。

  3. 对于松散类型的 JavaScript,我很好奇:有没有像 C 一样的规则来确定在哪种情况下执行哪种转换?除此之外,上面的 JavaScript 代码num在进行比较之前将变量值从整数值转换为字符串值,反之亦然?

4

5 回答 5

21

是的,等号运算符应用的所有类型转换规则都在 ECMA-262 规范的The Abstract Equality Comparison Algorithm中进行了描述。

该算法可能看起来很复杂,但可以总结为以下几种情况:

  1. 两个操作数的类型相同:

    • 对于原语(字符串、数字、布尔值、空值、未定义)
      • 如果值完全相同,则返回 true
    • 对于对象类型
      • 如果两个引用指向同一个对象,则返回 true
  2. 如果两个操作数的类型不同

    • 如果一个操作数的类型是 Null 或 Undefined
      • 仅当另一个操作数值为null或时才返回真undefined
    • 如果其中一个操作数是布尔或数字类型
      • (经过一些步骤)将另一个操作数转换为数字并进行比较
  3. 如果一个操作数是一个对象,另一个是一个基元

    • 对Object进行Object-to-Primitive转换并再次比较

Object-to-Primitive 转换是通过一个名为 的抽象操作进行的ToPrimitive,该方法将尝试使用 internal[[PrimitiveValue]]方法将对象转换为原始值。

这将尝试弹出对象的valueOftoString方法,它将采用返回原始值的第一个值。

如果这两个方法不返回原语,或者它们不可调用,TypeError则抛出 a,例如:

1 == { toString:null } // TypeError!

上面的语句会产生一个TypeError,因为默认方法除了实际上是同一个对象实例( ,不是原始值)Object.prototype.valueOf之外没有做任何事情,而且我们正在设置一个自己的属性,它不是一个函数。thistoString

一个朋友制作的小工具,你可能会感兴趣,它显示了类型之间的所有步骤和递归比较:

于 2011-10-02T07:54:24.917 回答
6

在 JavaScript 中,有两个运算符可用于比较两个值:==and===运算符。

引用自 JavaScript The Definitive Guide 第 6 版:

相等运算符==类似于严格相等运算符 ( ===),但不那么严格。如果两个操作数的值不是同一类型,它会尝试一些类型转换并再次尝试比较。

严格相等运算符===评估其操作数,然后按如下方式比较两个值,不执行类型转换。

所以我建议你===一直使用以避免出现以下问题:

null == undefined // These two values are treated as equal. 
"0" == 0 // String converts to a number before comparing. 
0 == false // Boolean converts to number before comparing. 
"0" == false // Both operands convert to numbers before comparing.

PS我可以发布书中所写的整个“比较指南”,但它太长了;)告诉我,我会为你编辑我的帖子。

于 2011-10-02T07:51:42.797 回答
3

避免在 JavaScript 中进行隐式类型转换。在比较它们之前,请务必采取措施测试和/或转换单个值,以确保您将苹果与苹果进行比较。始终显式测试 undefined 以确定值或属性是否具有值,使用 null 表示对象变量或属性不引用任何对象,并转换和比较所有其他值以确保针对相同类型的值执行操作.

于 2011-12-27T00:14:59.463 回答
0

我知道这个问题已经回答了。我在下面给出的是几个转换的例子。这对 JavaScript 新手很有用。下面的输出可以与一般算法进行比较,以便于理解。

编码:

var values = ["123",
          undefined,
          "not a number",
          "123.45",
          "1234 error",
          "",
          "       ",
          null,
          undefined,
          true,
          false,
          "true",
          "false"
          ];

for (var i = 0; i < values.length; i++){
    var x = values[i];
    console.log("Start");
    console.log(x);
    console.log(" Number(x) = " + Number(x));
    console.log(" parseInt(x, 10) = " + parseInt(x, 10));
    console.log(" parseFloat(x) = " + parseFloat(x));
    console.log(" +x = " + +x);
    console.log(" !!x = " + !!x);
    console.log("End");
}

输出:

"Start"
"123"
" Number(x) = 123"
" parseInt(x, 10) = 123"
" parseFloat(x) = 123"
" +x = 123"
" !!x = true"
"End"

"Start"
undefined
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = false"
"End"

"Start"
"not a number"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"

"Start"
"123.45"
" Number(x) = 123.45"
" parseInt(x, 10) = 123"
" parseFloat(x) = 123.45"
" +x = 123.45"
" !!x = true"
"End"

"Start"
"1234 error"
" Number(x) = NaN"
" parseInt(x, 10) = 1234"
" parseFloat(x) = 1234"
" +x = NaN"
" !!x = true"
"End"

"Start"
""
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
"       "
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = true"
"End"

"Start"
null
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
undefined
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = false"
"End"

"Start"
true
" Number(x) = 1"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 1"
" !!x = true"
"End"

"Start"
false
" Number(x) = 0"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = 0"
" !!x = false"
"End"

"Start"
"true"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"

"Start"
"false"
" Number(x) = NaN"
" parseInt(x, 10) = NaN"
" parseFloat(x) = NaN"
" +x = NaN"
" !!x = true"
"End"
于 2016-01-15T16:44:53.283 回答
0

更好地使用下面的代码来理解隐式转换。

var values = [ 0 , 123, "0", "123", -0, +0, NaN, +NaN, -NaN, false, true, "false", "true", null, undefined, "null", "undefined", "", "GoodString", "  "];

for (var i = 0; i < values.length; i++){
    console.log("<<<<<<<<<<<<Starting comparing:  " + i + ">>>>>>>>>>>>>>>");
    for (var j = 0; j < values.length; j++){
		console.log(values[i],`==`, values[j]);
		console.log(eval(values[i] == values[j]));
	}
}

于 2017-11-09T19:28:19.583 回答