使用 == 比较整数与字符串时 JavaScript 中的隐式数据类型转换

发布于 2024-12-07 14:58:00 字数 475 浏览 3 评论 0原文

代码:

var num = 20;

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

问题:

  1. 在 C 编程中,我们有一个规则名称数据类型提升,其中当存在混合数据类型时(例如:整数和浮点数相加),整数将首先转换为浮点数,然后再转换为浮点数。

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

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

The code:

var num = 20;

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

The question:

  1. In C programming we have a rule name data type promotion, where when there's a mix of data type (example: addition of integer and floating point), the integer will first converted to floating point before the addition is being carry out.

  2. The code above will prompt me an alert box with the message "It works" that shows the if test condition is evaluate to true.

  3. For loosely typed JavaScript, I'm just curious: is there any rule like C that determines which conversion will be carry out in which situation? Besides that, the JavaScript code above converts num variable value from an integer value to string value before making comparison or vice versa?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

故人的歌 2024-12-14 14:58:00

是的,ECMA-262 规范中的抽象相等比较算法<中描述了 equals 运算符应用的所有类型转换规则。 /a>.

该算法可能看起来相当复杂,但可以概括为以下情况:

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

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

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

    • 对对象执行对象到基元的转换并再次比较

对象到基元转换是通过名为 ToPrimitive,此方法将尝试使用内部 [[PrimitiveValue]] 方法。

这将尝试弹出对象的 valueOftoString 方法,并且它将获取第一个返回原始值的值。

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

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

上面的语句将产生 TypeError 因为默认的 Object.prototype.valueOf 方法除了实际相同的对象实例(this,不是原始值)之外不会执行任何操作,并且我们正在设置自己的 toString 属性不是一个函数。

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

Yes, all the rules of type conversion applied by the equals operator are described on the ECMA-262 specification, in The Abstract Equality Comparison Algorithm.

The algorithm might look quite complex but it can be summarized to the following cases:

  1. The type the two operands is the same:

    • For primitives (String, Number, Boolean, Null, Undefined)
      • Return true if the value is exactly the same
    • For the Object type
      • Return true if the two references point to the same object
  2. If the types of the two operands differ

    • If the type of one operand is either Null or Undefined
      • Return true only if the other operand value is either null or undefined
    • If one of the operands is of type Boolean or Number
      • (after some steps) Convert the other operand to Number and compare
  3. If one of the operands is an Object and the other is a primitive

    • Perform Object-to-Primitive conversion on the Object and compare again

The Object-to-Primitive conversion is made through an abstract operation called ToPrimitive, this method will try to convert the object to a primitive value, using the internal [[PrimitiveValue]] method.

This will try to ejecute the object's valueOf and toString methods, and it will take the value of the first that returns a primitive value.

In the case those two methods don't return a primitive, or they aren't callable, a TypeError is thrown, e.g.:

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

The above statement will produce a TypeError because the default Object.prototype.valueOf method doesn't do anything more than actually the same object instance (this, not a primitive value) and we are setting an own toString property that's not a function.

A friend made small tool that might be interesting to you, it shows all the steps and recursive comparisons made between types:

叹倦 2024-12-14 14:58:00

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

引自 JavaScript 权威指南第 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 我可以发布书中写的整个“比较指南”,但它太长了;)只需告诉我和我将为您编辑我的帖子。

In JavaScript, there are two operators that can be used to compare two values: the == and === operators.

Quoted from JavaScript The Definitive Guide 6th Edition:

The equality operator == is like the strict equality operator (===), but it
is less strict. If the values of the two operands are not the same type,
it attempts some type conversions and tries the comparison again.

And

The strict equality operator === evaluates its operands, and then compares the
two values as follows, performing no type conversion.

So I suggest that you use === all the time to avoid problems like:

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.

P.S. I could post the entire "comparison guidelines" as written in the book but it's too long ;) Just tell me and I'll edit my post for you.

人生百味 2024-12-14 14:58:00

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

Avoid implicit type conversion in JavaScript. Always take steps to test and/or convert individual values before comparing them to ensure you are comparing apples to apples. Always test explicitly for undefined to determine if a value or property has a value, use null to indicate that object variables or properties do not refer to any object, and convert & compare all other values to ensure operations are performed against values of the same type.

你与清晨阳光 2024-12-14 14:58:00

我知道问题已经得到解答。我下面给出的是一些转换的示例。对于 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"

I know the question has been answered. What I have given below is an example of few conversions. It will be useful for someone who is new to JavaScript. The below output can be compared with the general algorithm for an easy understanding.

The code:

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");
}

The output:

"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"
柠檬色的秋千 2024-12-14 14:58:00

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

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]));
	}
}

Better use below code for understanding implicit conversion.

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]));
	}
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文