JavaScript中的类型强制到底是什么?


122

JavaScript中的类型强制到底是什么?

例如,使用==代替===


21
(true == 1) => true/ (true === 1) => false
VisioN 2013年

5
@VisioN您的评论根本没有帮助,我问:“为什么”会发生?
gespinha

3
之所以如此,是因为JavaScript是用这种方式开发的。我的评论应该回答您的主要问题:Java语言中的Type Coercion到底是什么?
VisioN

6
通过YDJS:“将值从一种类型转换为另一种类型,通常在显式完成时称为“类型转换”,而在隐式完成时称为“强制转换”(由值的使用规则决定)。- github.com/getify/You-Dont-Know-JS/blob/master/...
mattLummus

Answers:


177

类型强制意味着当一个运算符的操作数是不同类型时,其中一个将被转换为另一个操作数类型的“等效”值。例如,如果您这样做:

boolean == integer

布尔操作数将被转换为整数:false变为0true变为1。然后将这两个值进行比较。

但是,如果您使用非转换比较运算符===,则不会发生这种转换。当操作数是不同类型时,此运算符将返回false,并且仅在它们属于相同类型时才比较这些值。


1
我如何将其置于实际情况下?如果===要比较一个值是否等于另一个值,我是否不应该总是使用?
gespinha

1
这取决于您在做什么。请参阅链接的问题。
Barmar

8
@GEspinha很好,这是使用宽松类型的语言的“艺术”。有人这样认为,并且通常认为松散类型的语言是编程世界的祸害。但是,如果您知道自己在做什么,它可以使代码更短,更灵活。
Crayon Violent

2
@Barmar是否也适用> , <
罗伊·纳米尔

2
一个很好的参考和解释上的胁迫:github.com/getify/You-Dont-Know-JS/blob/master/...
格雷格·贝尔

56

让我们从简短的类型系统介绍开始,我认为它将帮助您理解类型强制的一般概念。

一种语言的类型系统定义了一些规则,这些规则告诉我们该语言中存在哪些数据类型以及如何使用不同的运算符将它们组合在一起。例如,一个这样的规则可能指定加号(+)运算符仅作用于数字。这些规则的主要目的是防止您用脚射击。但是,当程序员在程序中违反该规则时会发生什么?即使语言认为这些表达式没有任何意义,也没有什么可以阻止程序员输入{} + {}“hello” + 5在程序中进行编程。

在这些情况下最终发生的情况取决于语言对其类型规则的严格程度。

语言类型系统经常在违反规则的情况下占据两个位置之一:

  1. 说“嘿,那不酷!” 并立即使您的程序崩溃。
  2. 说“我不能用{}做任何事情……但是我可以用数字做某事”,然后尝试将{}转换为数字。

类型系统将其规则放在首位的语言俗称“强类型”语言。他们严格禁止您违反规则。那些采用第二种方法的语言(例如JavaScript)被称为“弱类型”或“松类型”语言。当然,您可以违反规则,但是当它强制转换程序中描述的数据类型以遵守其规则时,请不要感到惊讶。这种行为被称为…(鼓卷)... 型强制

现在,让我们看一下JavaScript中的一些示例。首先,让我们从不导致类型强制的表达式开始。

5 + 5

将+运算符与两个数字一起使用是完全有效的。该程序将+表示为“加”,并愉快地将两个数字相加。无需转换。

但是关于 …

[] + 5

哦哦 在JavaScript中,+可以表示添加两个数字或连接两个字符串。在这种情况下,我们既没有两个数字也没有两个字符串。我们只有一个数字和一个对象。根据JavaScript的类型规则,这没有逻辑意义。由于它原谅您违反了规则,因此它不会崩溃而不是崩溃。那么JavaScript做什么呢?好吧,它知道如何连接字符串,因此将[]和5都转换为字符串,结果是字符串值“ 5”。

比较运算符==和有===什么关系?为什么有两个比较运算符?

==无法避免JavaScript的类型转换行为。诸如之类的表达式5 == “5”将评估为true,因为JavaScript会尝试转换其中之一,以便比较相同类型的数据。

在许多情况下,这是不希望的,因为您可能想知道您要比较的某些数据是否属于不同类型,以便您可以决定如何处理。这就是===运算符的作用。当您使用时===,将不会进行类型转换。因此,该表达式5 === “5”将计算为false。


4
感谢您的解释,尤其是“一种语言类型的系统通常会担任两个职位之一”
Humoyun Ahmad

1
这应该是公认的答案,因为它显示了多个方面的自动类型强制,而不仅仅是==比较示例。这个答案在回答问题和消除所有歧义方面做得更好。感谢您抽出宝贵的时间写出来。
乍得

6

在Python中,如果尝试添加字符串和整数,则会出现错误:

>>> "hi" + 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

但是在JavaScript中,您不需要。将10获取转换为字符串:

> "hi" + 10
"hi10"

“类型强制”只是上面的一个错误名称。实际上,两种语言都没有Java或C的“类型”或具有静态类型系统的其他语言。语言如何处理各种非静态类型的值之间的交互是选择和约定的问题。


1
我认为您所举的示例存在一些问题。您所建议的JS示例可以与Java和C#完美结合。因此,根据此答案,如果得出结论,Java和C#支持类型的强制转换并非完全正确……
Romeo Sierra

3

让我用以下示例解释类型强制

Type Coercion意味着Javascript自动(即时)将变量从一种数据类型转换为另一种数据类型

例如:123 + "4"通常会引发错误,但是在Javascript中,由于类型强制,它会导致1234字符串

if(23 == "23"){
    console.log(" this line is inside the loop and is executed ");
}

在上面的代码中,由于类型为强制-JavaScript认为23(number)和"23"(string)是同一回事。这使条件成立,并打印console.log

在另一种情况下

if(23 === "23"){
   console.log(" this line is inside the loop and is NOT executed");
}

===情况下,JavaScript没有做类型强制,并且因为23是一个数字,"23"是String,并因为===这两种数据类型是不同的,导致病情的假。它不打印console.log

简单来说

在这种情况下,=它是一个赋值运算符-赋值如var a = 3;,等等

(下面的运算符供比较)

在这种情况下,==JavaScript会将数据类型转换/强制转换为另一个,然后进行比较。

在这种情况下,=== JavaScript不会转换/强制转换数据类型

为了避免错误和用于调试目的===,通常使用

请让我知道以上信息的准确性。


2

什么是胁迫:

当Javascript引擎必须执行某种需要其数据为某种类型的操作时,会在javascript中发生类型强制。当引擎遇到不适用于该操作的某种类型的数据时,它将随后将数据强制为某种类型。这是必需的,因为javascript中的变量是动态类型的,这意味着可以为给定变量分配任何类型的值。

例:


if(1){
  // 1 gets coerced to true
}


if(4 > '3') {
  // 3 gets coerced into a number
}


44 == "44"  // true, the string 44 gets converted to a nr

布尔强制:

在javascript强制中,true除强制以下值之外,所有值都将转换为false

console.log(!!"");         // false
console.log(!!0);          // false
console.log(!!null);       // false
console.log(!!undefined);  // false
console.log(!!NaN);        // false
console.log(!!false);      // false

还要注意,在上面的示例中,double是!使用运算符。!标记运算符将一个值强制为具有相反值的布尔值。我们可以两次使用此运算符将任何值转换为布尔值。


1

a == b这就意味着JavaScript将评估ab基于其中的值是否可以同样评价。例如,false == 0将评估为true,因为0也是布尔值false的值。但是,false === 0将评估为假,因为严格比较,0与假的物理值不同。另一个示例是false == ''So松散比较与严格比较,因为javascript是一种松散类型的语言。也就是说,javascript将尝试基于代码的上下文来转换变量,如果不严格比较它们,则具有使事物相等的效果。php也有这种行为。


0 is not the same physical value as false。IMO实际上false完全0在内存中。我宁愿说它们在类型上是不同的,因为它false是布尔值,而是0整数。
VisioN

1

类型强制是将值从一种类型转换为另一种类型的过程(例如,字符串转换为数字,对象转换为布尔值,等等)。任何类型,无论是原始类型还是对象,都是强制类型的有效主体。回想一下,原语是:数字,字符串,布尔值,空值,未定义+符号(在ES6中添加)。

隐式和显式强制 类型强制可以是显式和隐式的。

当开发人员通过编写适当的代码(例如)表达意图在类型之间进行转换时Number(value),这称为显式类型强制(或类型转换)。

由于JavaScript是一种弱类型的语言,因此值也可以自动在不同类型之间转换,这称为隐式类型强制。通常在将运算符应用于不同类型的值(如 1 == null,,2/’5')时发生null + new Date(),或者它可以由周围的上下文触发,如with if (value) {…},其中value被强制转换为boolean。

一个不会触发隐式类型强制的运算符是===,称为严格相等运算符。==另一方面,如果需要,宽松的相等运算符会同时执行比较和类型强制。

隐式类型强制是一把双刃剑:它是挫折和缺陷的重要来源,而且是一种有用的机制,它使我们可以编写更少的代码而不会损失可读性。

三种类型的转换 首先要知道的规则是JavaScript中只有三种类型的转换:

  • 布尔值
  • 编号

其次,基元和对象的转换逻辑工作方式不同,但是基元和对象只能以这三种方式转换。

让我们先从原语开始。

字符串转换

要将值显式转换为字符串,请使用String()函数。当任何操作数为字符串时,隐式强制由二进制+运算符触发:

String(123) // explicit
123 + ''    // implicit

如您所料,所有原始值都会自然转换为字符串:

String(123)                   // '123'
String(-12.3)                 // '-12.3'
String(null)                  // 'null'
String(undefined)             // 'undefined'
String(true)                  // 'true'
String(false)                 // 'false'

符号转换有点棘手,因为它只能显式转换,而不能隐式转换。

String(Symbol('my symbol'))   // 'Symbol(my symbol)'
'' + Symbol('my symbol')      // TypeError is thrown

布尔转换

要将值显式转换为布尔值,请应用该Boolean()函数。隐式转换发生在逻辑上下文中,或由逻辑运算符(|| && !)触发。

Boolean(2)          // explicit
if (2) { ... }      // implicit due to logical context
!!2                 // implicit due to logical operator
2 || 'hello'        // implicit due to logical operator

注意:逻辑运算符(例如)在|| and &&内部进行布尔转换,但是实际上返回原始操作数的值,即使它们不是布尔值也是如此。

// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123;   // x === 123

只要只有两种可能的布尔转换结果:true或false,就更容易记住虚假值列表。

Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false

不在列表中的任意值被转换为true,包括objectfunctionArrayDate,用户定义的类型,等等。符号是真实的价值。空对象和数组也是真实值:

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true

数值转换

对于显式转换,只需应用Number()功能,就像使用Boolean()和一样String()

隐式转换是棘手的,因为它在更多情况下被触发:

  • 比较运算符(>,<,<=,> =)

  • 按位运算符(|&^〜)

  • 算术运算符(-+ * /%)。请注意,当任何操作数为字符串时,binary +不会触发数字转换。

  • 一元+运算符

  • 松散相等运算符==(包括!=)。

    请注意,当两个操作数均为字符串时,==不会触发数字转换。

    Number('123')//显式+'123'//隐式123!='456'//隐式4>'5'//隐式5 / null //隐式true | 0 //隐式

这是原始值如何转换为数字的方法:

Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("\n")                   // 0
Number(" 12s ")                // NaN
Number(123)                    // 123



0
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"

最初声明为字符串的变量示例,使用!强制转换为布尔值!算子


3
请详细说明您的答案。仅代码答案并没有真正的帮助。
cezar

3
我个人认为代码只是示例简洁,自我解释且非常有用的示例,我想这是个人观点的问题
Mister P

0

类型强制是将值从一种类型转换为另一种类型的过程(例如,字符串转换为数字,对象转换为布尔值,等等)。任何类型,无论是原始类型还是对象,都是强制类型的有效主体。回想一下,原语是:数字,字符串,布尔值,空值,未定义+符号(在ES6中添加)。

类型强制可以是显式的也可以是隐式的。

当开发人员通过编写适当的代码(例如Number(value))表达在类型之间进行转换的意图时,这称为显式类型强制(或类型转换)。

由于JavaScript是弱类型语言,因此值也可以自动在不同类型之间转换,这称为隐式类型强制。当您将运算符应用于不同类型的值(例如1 == null,2 /'5',null + new Date())时,通常会发生这种情况,或者它可以由周围的上下文触发,例如if(value){… },其中值被强制为布尔值。

这是隐式类型强制的一些示例:

true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == x
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0

阅读更多:https : //www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/


-2

如果数据类型彼此不相等,则会发生强制转换。像3 ==“ 3”或boolen ==整数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.