使用==比较整数和字符串时,JavaScript中的隐式数据类型转换
Implicit data type conversion in JavaScript when comparing integer with string using ==
代码:
var num = 20;
if(num == "20")
{
alert("It works");
}
else
{
alert("Not working");
}
问题:
在C编程中,我们有一个名为数据类型提升的规则,当存在混合数据类型时(例如:整数和浮点数相加),在进行加法之前,整数将首先转换为浮点数。
上面的代码将提示我一个警告框,其中包含
"It works"
消息,显示if
测试条件被评估为true。对于松散类型的JavaScript,我只是好奇:是否有像C这样的规则决定在哪种情况下执行哪种转换?除此之外,上面的JavaScript代码转换
num
变量值从整数值到字符串值之前进行比较,反之亦然?
是的,所有由相等运算符应用的类型转换规则都在ECMA-262规范中描述,在抽象相等比较算法中。
这个算法可能看起来很复杂,但它可以概括为以下几种情况:
-
两个操作数的类型相同:
- 对于原语(字符串,数字,布尔值,Null,未定义)
- 如果值完全相同则返回true
- 对象类型
- 如果两个引用指向同一个对象返回true
- 对于原语(字符串,数字,布尔值,Null,未定义)
-
如果两个操作数的类型不同
- 如果一个操作数的类型为Null或Undefined
- 仅当另一个操作数为
null
或undefined
时返回true
- 仅当另一个操作数为
- 如果其中一个操作数是布尔类型或数字类型
- (经过一些步骤)将另一个操作数转换为Number并比较
- 如果一个操作数的类型为Null或Undefined
-
如果其中一个操作数是Object而另一个操作数是基元
- 在对象上执行对象到原语的转换并再次比较
对象到原语的转换是通过一个叫做ToPrimitive
的抽象操作完成的,这个方法将尝试使用内部的[[PrimitiveValue]]
方法将对象转换为一个原语值。
这将尝试弹出对象的valueOf
和toString
方法,它将取第一个返回原始值的方法的值。
如果这两个方法不返回原语,或者它们不可调用,则抛出TypeError
,例如:
1 == { toString:null } // TypeError!
上面的语句将产生一个TypeError
,因为默认的Object.prototype.valueOf
方法除了实际相同的对象实例(this
,不是原始值)之外没有做任何事情,并且我们正在设置一个自己的toString
属性,它不是函数。
一个朋友做的小工具,你可能会感兴趣,它显示了所有的步骤和递归比较类型:
- JS强制转换工具
在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.
注:我可以把书中写的整个"比较指南"贴出来,但是太长了;)
避免JavaScript中的隐式类型转换。在比较它们之前,总是采取步骤来测试和/或转换单个值,以确保你是在逐个比较。始终显式地测试undefined以确定值或属性是否有值,使用null表示对象变量或属性不引用任何对象,并转换&比较所有其他值,以确保对相同类型的值执行操作。
我知道这个问题已经有答案了。我下面给出的是一些转换的例子。它对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"
最好使用下面的代码来理解隐式转换。
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]));
}
}
- javascript解释器如何理解变量的数据类型
- 从查询字符串参数推断出正确的数据类型
- 为什么不'我们在javascript中使用函数参数的数据类型
- 基于数据类型的编辑框的汇总列表
- 如何降低此函数的复杂性,该函数根据数据类型进行回调
- 比较和分配数据类型的困难
- 在javascript中调用函数/对象引用时,可容纳任何数据类型
- E4X中是否有一种方法可以将基元数据类型的XMLList转换为类似于Array.join()的Array
- Highcharts系列.数据数据类型限制
- 如何在php循环中显示隐藏的数据类型
- 如何从标签数据类型=“;无线电”;
- 将数据结构转换为二进制数据
- 谷歌地图数据类型抛出类型错误:can't将未定义转换为对象
- QT 哪些 QML/C++ 数据类型可以转换为 JSON
- JavaScipt的数据类型转换对于“==”运算符究竟是如何工作的
- 使用==比较整数和字符串时,JavaScript中的隐式数据类型转换
- 转换32位无符号Real"数据类型(分成两个16位签名字)到javascript
- google levis在R中的数据类型转换似乎不起作用
- 主干数据类型 - 类型转换
- Javascript中的数据类型转换