jojo.zhou

运算符 • 致不耐烦的JSer(beta)

原文链接: exploringjs.com

广告位...

11. 操作符

11.1. 运算符两个重要的规则

  • 强制让运算数变为合适的类型

  • 大多数运算符只对基本类型起作用

11.1.1. 运算符两个重要的规则

一个运算符操作的的数据类型不匹配, JS基本不会抛出异常。相反,它会自动进行强制类型转换。以便于这样看起来是正常运算的。让我们来看下面两个例子。

首先,一个乘法运算只可以让两个数字正常工作,因此,在相乘之前,他会将字符转换成数字。

> '7' * '3'
21

其次, 用于访问对象属性的运算符[]只能处理字符串或者symbol。其他的值会被强制转换成字符串。其他的字都会转换成字符串:

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

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

11.1.2. 大多数运算符只对基本类型起作用

对于JS运算符需要要记住的规则是

大多数运算符只对基本类型起作用。

如果运算数是对象,则经常会被强制转换成基本类型。

举例:

> [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'

11.2. 加号plus

在JS中,加号按以下方式工作:首先它会将运算数转换成基本类型,然后它会切到两种模式之一:

  • 字符串模式:如果一个被转换成的基本类型有一个是字符串,那么另外一个也会被转换成字符串,最后字符串会进行连接。

  • 数字模式:除此之外,两边的运算数会被转换成数字,然后进行相加。

字符串模式可以让你使用+去连接各个字符串:

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

数字模式意味着:如果运算符两边都不是数字(或者一个对象变成了字符串)那么都会被变成数字:

> 4 + true
5

(Number(true) is 1.)

11.3. 赋值运算符

11.3.1. 基本的赋值运算符

  • x = value

    给一个声明的变量赋值

  • const x = value

    同时进行声明和赋值。

  • obj.propKey = value

    给一个属性赋值

  • arr[index] = value

    给数组的某个元素赋值。

11.3.2. 复合赋值运算符

给出的运算符被复合,以下两种方式是相同的:

myvar op= value
myvar = myvar op value

举例来说,复合+,然后我们可以得到运算符+=它会像下面的工作:

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

assert.equal(str, '<b>Hello!</b>');

11.3.3. 全部的复合赋值运算符

  • 数学操作符:

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

    += 同样对字符串连接有效

  • 按位运算符:

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

11.4. 相等运算: == VS ===

JS 有两种等号运算符:宽松的相等(==)和严格的相等(===)。推荐总是使用后者判断是否相等。

11.4.1. 宽松相等(== and !=)

宽松相等是JS的特性之一。它经常会强制转换运算数,有些强制转换是有意义的:

> '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

最后,== 允许了undefined和null相等

> undefined == null
true

11.4.2. 严格相等 (=== and !==)

严格相等从不会类型转换。两个相等的值一定会有相同的类型。让我们复习一遍之前的==运算符,然后看===是怎样工作的:

> 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

=== 运算符不允许undefined和null相等:

> undefined === null
false

11.4.3. 推荐:总是使用严格模式

推荐总是使用===。他会让你的代码可读性更高。把你从不得不思考怪异的==中解脱出来。

让我们看一下两个case:使用==的和我推荐的替代方案。

11.4.3.1. 使用 ==:比较一个数字和字符串

== 让你去判断一个值x是一个数字,或者作为字符串的数字,通过单个的比较:

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

我更喜欢以下两种替代方案:

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

你也可以在第一次遇见他的时候将它转换成数字。

11.4.3.2 ==: 比较undefined 和 null

使用==的另外一个case是比较undefined 或 null:

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

这段代码的问题在于,你无法保证是其他人也会用这种方式判断,或者有人有用meant === null的方式。

我更喜欢一下两者任意替代方式:

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

第二种替代方式是相对更常见,但是塔毁坏了一些在JS中的一些模式。 在 the chapter on booleans会解释到, 我们会看到现象与不好的地方。

11.5. 比较运算

Operator name
< 小于
<= 小于等于
> 大于
>= 大于等于

JS的比较运算符规则(tbl. 2) 对字符串和数字同样生效。

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

警告:这些运算符在比较人类语言中的文本(大写、重音等)时效果不佳。有关详细信息,请参阅字符串章节

11.6. 其他的运算符

Quiz

问答社区

评论

下一章: IV. 基本类型