12.运算符

原文: http://exploringjs.com/impatient-js/ch_operators.html

12.1。理解运算符

JavaScript 的运算符可能看起来很古怪。使用以下两个规则,它们更容易理解:

  • 运算符将其操作数强制为适当的类型
  • 大多数运算符只使用原始值

12.1.1。运算符将其操作数强制为适当的类型

如果运算符获取的操作数不具有正确的类型,则很少会抛出异常。相反,它 _ 强制 _(自动转换)操作数,以便它可以使用它们。我们来看两个例子。

首先,乘法运算符只能用于数字。因此,它在计算结果之前将字符串转换为数字。

> '7' * '3'
21

其次,用于访问对象属性的方括号运算符([ ])只能处理字符串和符号。所有其他值都强制为字符串:

const obj = {};
obj['true'] = 123;

// Coerce true to the string 'true'
assert.equal(obj[true], 123);

12.1.2。大多数运算符只使用原始值

如前所述,大多数运算符仅使用原始值。如果操作数是对象,则通常将其强制转换为原始值。例如:

> [1,2,3] + [4,5,6]
'1,2,34,5,6'

为什么?加号运算符首先将其操作数强制转换为原始值:

> String([1,2,3])
'1,2,3'
> String([4,5,6])
'4,5,6'

接下来,它连接两个字符串:

> '1,2,3' + '4,5,6'
'1,2,34,5,6'

12.2。加号运算符(+

plus 运算符在 JavaScript 中如下工作:

  • 首先,它将两个操作数转换为原始值。然后它切换到以下两种模式之一:
    • 字符串模式:如果两个原始值中的一个是字符串,则它将另一个转换为字符串,连接两个字符串并返回结果。
    • 数字模式:否则,它将两个操作数转换为数字,添加它们并返回结果。

字符串模式让我们使用+来组合字符串:

> 'There are ' + 3 + ' items'
'There are 3 items'

数字模式意味着如果操作数都不是一个字符串(或一个成为字符串的对象),那么所有内容都被强制转换为数字:

> 4 + true
5

Number(true)1

12.3。分配运算符

12.3.1。普通赋值运算符

普通赋值运算符用于更改存储位置:

x = value; // assign to a previously declared variable
obj.propKey = value; // assign to a property
arr[index] = value; // assign to an Array element

变量声明中的初始值设定项也可以视为赋值形式:

const x = value;
let y = value;

12.3.2。复合赋值运算符

给定运算符op,以下两种分配方式是等效的:

myvar op= value
myvar = myvar op value

例如,如果op+,那么我们得到如下工作的运算符+=

let str = '';
str += '<b>';
str += 'Hello!';
str += '</b>';

12.3.3。所有复合赋值运算符的列表

  • 算术运算符:

    += -= *= /= %= **=
    

    +=也适用于字符串连接

  • 按位运算符:

    <<= >>= >>>= &= ^= |=
    

12.4。平等:=====

JavaScript 有两种相等运算符:松散相等(==)和严格相等(===)。建议总是使用后者。

12.4.1。松散平等(==!=

松散的平等是 JavaScript 的怪癖之一。它经常强制操作。其中一些强制措施是有道理的:

> '123' == 123
true
> false == 0
true

其他人不那么:

> '' == 0
true

如果(并且仅当!)另一个操作数是原始的,对象被强制转换为基元:

> [1, 2, 3] == '1,2,3'
true
> ['1', '2', '3'] == '1,2,3'
true

如果两个操作数都是对象,则它们只有在相同的对象时才相等:

> [1, 2, 3] == ['1', '2', '3']
false
> [1, 2, 3] == [1, 2, 3]
false

> const arr = [1, 2, 3];
> arr == arr
true

最后,==认为undefinednull相等:

> undefined == null
true

== 的其他名称

12.4.2。严格平等(===!==

严格的平等永远不会强迫。如果两个值具有相同的类型,则它们仅相等。让我们重新审视我们之前与==运算符的交互,看看===运算符的作用:

> false === 0
false
> '123' === 123
false

如果该值是同一个对象,则该对象仅等于另一个值:

> [1, 2, 3] === '1,2,3'
false
> ['1', '2', '3'] === '1,2,3'
false

> [1, 2, 3] === ['1', '2', '3']
false
> [1, 2, 3] === [1, 2, 3]
false

> const arr = [1, 2, 3];
> arr === arr
true

===运算符不认为undefinednull相等:

> undefined === null
false

=== 的另一个名称

_ 三等于 _ 是===的另一个名称。

12.4.3。建议:始终使用严格的平等

我建议总是使用===。它使您的代码更容易理解,并使您不必考虑==的怪癖。

让我们看看==的两个用例以及我建议做的事情。

12.4.3.1。 ==的用例:与数字或字符串比较

==允许您检查值x是数字还是数字作为字符串 - 只需一次比较:

if (x == 123) {
  // x is either 123 or '123'
}

我更喜欢以下两种选择之一:

if (x === 123 || x === '123') ···
if (Number(x) === 123) ···

您第一次遇到它时也可以将x转换为数字。

12.4.3.2。 ==的用例:与undefinednull比较

==的另一个用例是检查值xundefined还是null

if (x == null) {
  // x is either null or undefined
}

这段代码的问题在于你无法确定是否有人打算以这种方式编写或者如果他们输错了并且意味着=== null

我更喜欢以下两种选择之一:

if (x === undefined || x === null) ···
if (x) ···

第二种选择比使用==更加草率,但它在 JavaScript 中是一种成熟的模式(将在关于布尔的章节中详细解释,我们在其中看到真实性和虚假性)。

12.4.4。甚至比===更严格:Object.is()

方法Object.is()比较两个值:

> Object.is(123, 123)
true
> Object.is(123, '123')
false

它甚至比===更严格。例如,它认为NaN涉及数字的计算的误差值等于它自己:

> Object.is(NaN, NaN)
true
> NaN === NaN
false

这偶尔会有用。例如,您可以使用它来实现 Array 方法.indexOf()的改进版本:

const myIndexOf = (arr, elem) => {
  return arr.findIndex(x => Object.is(x, elem));
};

myIndexOf()在数组中找到NaN,而.indexOf()则不:

> myIndexOf([0,NaN,2], NaN)
1
> [0,NaN,2].indexOf(NaN)
-1

结果-1表示.indexOf()无法在 Array 中找到其参数。

12.5。订购运算符

Table 3: JavaScript’s ordering operators.

操作者 名称
< 少于
<= 小于等于
> 比...更棒
>= 大于或等于

JavaScript 的排序运算符(tbl。 3 )适用于数字和字符串:

> 5 >= 2
true
> 'bar' < 'foo'
true

<=>=基于严格的平等。

订购运算符不适合人类语言

排序操作符不能很好地用于比较人类语言中的文本,例如,当涉及大写或口音时。有关详细信息,请参阅关于字符串的章节。

12.6。各种其他运算符

  • 逗号运算符a, b
  • void运算符void 0
  • 布尔运算符,字符串,数字,对象的运算符:在本书的其他地方介绍。

测验

参见测验应用程序


书籍推荐