其他分享
首页 > 其他分享> > 妖怪的梦路·灵气滤管篇

妖怪的梦路·灵气滤管篇

作者:互联网

运算符

Vis Filter。侵删


文章目录


一、算数运算符

1.概述

JavaScript提供十个算术运算符。

2.加法运算符

①.基本规则

1 + 1 // 2
true + true // 2
1 + true // 2

加法运算符+,用来求两个数值的和。
非数值的也行。true会被转成1

如果是两个字符串相加,加法运算符就会变成连接运算符:

'a' + 'bc' // "abc"

返回一个新的字符串,把两个原字符串连起来。

如果是一个字符串和一个非字符串,那非字符串就会被转成字符串,再连接到一起。

1 + 'a' // "1a"
false + 'a' // "falsea"

加法运算符是在运行时决定,到底相加还是连接。
所以运算子的不同会导致不同的行为,这种现象叫重载。

'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"

第一行先将4转成字符串,再与'3'连接,得出的'34'又把5转成了字符串,所以最终得到"345"

第二行先算出7,再转成字符串与'5'连接。

除了加法运算符,其他算术运算符,都不会发生重载。

1 - '2' // -1
1 * '2' // 2
1 / '2' // 0.5

规则都是先将字符串转为数值,再运算。

②.对象的相加

如果运算子是对象,则必须先转成原始类型的值,再相加。

var obj = { p: 1 };
obj + 2 // "[object Object]2"

对象obj转成原始类型的值是[object Object],再加2就这样了。

对象转为原始类型的值的过程:

首先调用valueOf方法,一般这个方法总是返回对象本身。

var obj = { p: 1 };
obj.valueOf() // { p: 1 }

然后再调用对象的toString方法,将其转为字符串。

var obj = { p: 1 };
obj.valueOf().toString() // "[object Object]"

这个方法默认返回[object Object]

所以可以自己定义valueOf方法或toString方法,得到想要的结果。

var obj = {
  valueOf: function () {
    return 1;
  }
};

obj + 2 // 3

上面定义了obj对象的valueOf方法返回1,所以obj + 2就得到了3,在这个例子里,由于valueOf方法直接返回了一个原始类型的值,所以就不再调用toString方法。

下面是自定义toString

var obj = {
  toString: function () {
    return 'hello';
  }
};

obj + 2 // "hello2"

对象objtoString返回字符串hello,因为只要有一个运算子是字符串,加法就会变成连接,返回连接后的字符串。

关于这里有个特例,如果运算子是一个Date对象的实例,那么就优先执行toString方法。

var obj = new Date();
obj.valueOf = function () { return 1 };
obj.toString = function () { return 'hello' };

obj + 2 // "hello2"

上面obj是一个Date对象的实例,而且自定义了两个方法,结果toString优先执行。

3.余数运算符

12 % 5 // 2

余数运算符%返回前一个运算子被后一个运算子除,所得的余数。

运算结果的正负由第一个运算子的正负决定:

-1 % 2 // -1
1 % -2 // 1

所以为了得到负数的正确余数,可以先使用绝对值函数:

// 错误的写法
function isOdd(n) {
  return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false

// 正确的写法
function isOdd(n) {
  return Math.abs(n % 2) === 1;
}
isOdd(-5) // true
isOdd(-4) // false

余数运算符还能用于浮点数的运算,不过因为浮点数不是精确的值,所以无法得到很准确的结果。

6.5 % 2.1
// 0.19999999999999973

4.自增与自减运算符

这两个是一元运算符,只需要一个运算子。
将运算子转为数值,然后加1或减1。
它们会修改原始变量

var x = 1;
++x // 2
x // 2

--x // 1
x // 1

运算后,变量的值发生变化,这叫运算的副作用,
自增与自减是仅有的两个具有副作用的运算符,其他运算符都不会改变变量值。

这两个运算符放在变量之后,会先返回变量操作前的值,再进行自增或自减。
放在变量之前,会先进行自增或自减,再返回变量操作后的值。

var x = 1;
var y = 1;

x++ // 1
++y // 2

5.数值运算符,负数值运算符

数值运算符同样也是+,但它是一元运算符,而加法是二元。

数值运算符可以将任何值转为数值,与Number函数相同。

+true // 1
+[] // 0
+{} // NaN

NaN也是数值。

负数值运算符使用-,同样将一个值转为数值,不过得到的值正负相反。
连用两个负数值运算符,相当于数值运算符。

var x = 1;
-x // -1
-(-x) // 

它们都返回一个新的值,而不改变原始变量的值。

6.指数运算符

指数运算符**完成指数运算,前一个运算子是底数,后一个是指数。

2 ** 4 // 16

指数运算符是右结合,即多个指数运算符连用时,先进行右边的计算。

// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512

7.赋值运算符

用于给变量赋值。

最常见的是等号=

// 将 1 赋值给变量 x
var x = 1;

// 将变量 y 的值赋值给变量 x
var x = y;

还能与其他运算符结合,形成变体。

// 等同于 x = x + y
x += y

// 等同于 x = x - y
x -= y

// 等同于 x = x * y
x *= y

// 等同于 x = x / y
x /= y

// 等同于 x = x % y
x %= y

// 等同于 x = x ** y
x **= y

下面还有一些与位运算符的结合:

// 等同于 x = x >> y
x >>= y

// 等同于 x = x << y
x <<= y

// 等同于 x = x >>> y
x >>>= y

// 等同于 x = x & y
x &= y

// 等同于 x = x | y
x |= y

// 等同于 x = x ^ y
x ^= y

这些复合赋值运算符,都是先进行运算,再将得到的值赋给左边的变量。

二、比较运算符

1.概述

比较运算符用于比较两个值的大小,然后返回布尔值。

2 > 1 // true

比较运算符可以比较各种类型的值,不止是数值。

JavaScript提供8个比较运算符:

这八个分为两类,相等比较与非相等比较。

对于非相等的比较,算法是先看两个运算子是否都是字符串,如果是的话,就按Unicode码点比较,否则将两个运算子都转为数值,再比较数值大小。

2.非相等运算符

①.字符串的比较

'cat' > 'dog' // false
'cat' > 'catalog' // false

字符串按照字典顺序比较。
JavaScript内部先比较首字符的unicode码点,如果相等,就比较第二个字符的unicode码点,以此类推。

'cat' > 'Cat' // true'

c的码点(99)大于C的码点(67),所以返回true

所有字符都有unicode码点,所以汉字也能比较。

'大' > '小' // false

分别是22823和23567。所以大。

②.非字符串的比较

如果两个运算子中,至少有一个不是字符串,需要分成两种情况。

1)原始类型值

如果两个运算子都是原始类型的值,就先转为数值再比较。

5 > '4' // true
// 等同于 5 > Number('4')
// 即 5 > 4

true > false // true
// 等同于 Number(true) > Number(false)
// 即 1 > 0

2 > true // true
// 等同于 2 > Number(true)
// 即 2 > 1

字符串和布尔值都会先转成数值,再进行比较。

一切值与NaN使用非相等运算符比较,返回的都是false

1 > NaN // false
1 <= NaN // false
'1' > NaN // false
'1' <= NaN // false
NaN > NaN // false
NaN <= NaN // false

2)对象

如果运算子是对象,会转为原始类型的值,再进行比较。

var x = [2];
x > '11' // true
// 等同于 [2].valueOf().toString() > '11'
// 即 '2' > '11'

x.valueOf = function () { return '1' };
x > '11' // false
// 等同于 [2].valueOf() > '11'
// 即 '1' > '11'

对象转换为原始类型值,过程是先使用valueOf方法,如果返回的还是对象就再调用toString方法。

两个对象之间的比较也是这样。

[2] > [1] // true
// 等同于 [2].valueOf().toString() > [1].valueOf().toString()
// 即 '2' > '1'

[2] > [11] // true
// 等同于 [2].valueOf().toString() > [11].valueOf().toString()
// 即 '2' > '11'

{ x: 2 } >= { x: 1 } // true
// 等同于 { x: 2 }.valueOf().toString() >= { x: 1 }.valueOf().toString()
// 即 '[object Object]' >= '[object Object]'

4.严格相等运算符

JavaScript有两种相等运算符,=====

相等运算符==比较两个值是否相等,如果两个值不是同一类型,就先转成同一个类型,再比较。

严格相等运算符===比较两个值是否为同一个值,如果两个值不是同一类型,直接返回false

①.不同类型的值

1 === "1" // false
true === "true" // false

②.同一类型的值

1 === 0x1 // true

十进制的1和十六进制的1,类型和值都相等,所以返回true

NaN与任何值都不相等,正0等于负0

NaN === NaN  // false
+0 === -0 // true

③.复合类型值

两个复合类型的数据比较时,不是比较值是否相等,而是比较它们是否指向同一个地址。

{} === {} // false
[] === [] // false
(function () {} === function () {}) // false

如果两个变量引用同一个对象,则它们相等。

var v1 = {};
var v2 = v1;
v1 === v2 // true

关于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。

var obj1 = {};
var obj2 = {};

obj1 > obj2 // false
obj1 < obj2 // false
obj1 === obj2 // false

④.undefined和null

这两个与自身严格相等。

undefined === undefined // true
null === null // true

用于变量声明后默认是undefined,所以两个声明但未赋值的变量是相等的。

var v1;
var v2;
v1 === v2 // true

5.严格不相等运算符

1 !== '1' // true
// 等同于
!(1 === '1')

它的算法就是先求严格相等运算符的结果,然后返回相反值。

6.相等运算符

相等运算符用来比较相同类型的数据时,与严格相等运算符一样。

1 == 1.0
// 等同于
1 === 1.0

比较不同类型的数据时,相等运算符先将数据进行类型转换,然后再用严格相等运算符比较。

①.原始类型值

1 == true // true
// 等同于 1 === Number(true)

0 == false // true
// 等同于 0 === Number(false)

2 == true // false
// 等同于 2 === Number(true)

2 == false // false
// 等同于 2 === Number(false)

'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1

'' == 0 // true
// 等同于 Number('') === 0
// 等同于 0 === 0

'' == false  // true
// 等同于 Number('') === Number(false)
// 等同于 0 === 0

'1' == true  // true
// 等同于 Number('1') === Number(true)
// 等同于 1 === 1

'\n  123  \t' == 123 // true
// 因为字符串转为数字时,省略前置和后置的空格

②.对象与原始类型值比较

对象,包括数组和函数,与原始类型值比较时,先将对象转换成原始类型的值,再进行比较。

具体来说,是先调用对象的valueOf()方法,如果得到了原始类型的值,就按照上一节的规则比较;如果得到的还是对象,就再调用toString()方法,得到字符串,再比较。

// 数组与数值的比较
[1] == 1 // true

// 数组与字符串的比较
[1] == '1' // true
[1, 2] == '1,2' // true

// 对象与布尔值的比较
[1] == true // true
[2] == true // false
const obj = {
  valueOf: function () {
    console.log('执行 valueOf()');
    return obj;
  },
  toString: function () {
    console.log('执行 toString()');
    return 'foo';
  }
};

obj == 'foo'
// 执行 valueOf()
// 执行 toString()
// true

上面代码中,对象obj定义了valueOf()toString()方法,然后这个对象与'foo'比较,会依次调用两个方法,最后返回'foo'

③.undefined和null

undefined == undefined // true
null == null // true
undefined == null // true

false == null // false
false == undefined // false

0 == null // false
0 == undefined // false

undefinednull只有与自身比较或者互相比较时,才会返回true,与其他类型的值比较,都为false

④.相等运算符的缺点

相等运算符隐藏的类型转换,会有点令人迷惑。

0 == ''             // true
0 == '0'            // true

2 == true           // false
2 == false          // false

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

略微有点违反直觉,略略略微。

7.不相等运算符

1 != '1' // false

// 等同于
!(1 == '1')

它先求相等运算符的结果,然后返回相反值。

三、布尔运算符

1.概述

布尔运算符用于将表达式转为布尔值,有四个运算符。

2.取反运算符 !

取反运算符是一个感叹号,用来将布尔值变为相反值。

!true // false
!false // true

对于非布尔值,会先将其转为布尔值。
除了以下六个值取反后为true,其他都为false

!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true

!54 // false
!'hello' // false
![] // false
!{} // false

什么值经过取反运算后,都会变成布尔值。

如果对一个值连用两次取反运算符,相当于将其转为布尔值,与Boolean函数一样的作用。

!!x
// 等同于
Boolean(x)

这是一个常用的简便写法。

3.且运算符 &&

往往用于多个表达式的求值。
规则是,如果第一个运算子的布尔值为true,则返回第二个运算子的
如果第一个运算子的布尔值为false,则返回第一个运算子的值,且不再对第二个运算子求值。

't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""

var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1

这种跳过第二个运算子的机制,称为短路。
有人喜欢用它取代if结构,我不说是谁。

if (i) {
  doSomething();
}

// 等价于

i && doSomething();

这两种写法等价,最后一种很难看出目的,太危险了。

且运算符可以多个连用,此时返回第一个布尔值为false的表达式的值;
如果所有表达式的布尔值都是true,就返回最后一个表达式的值。

true && 'foo' && '' && 4 && 'foo' && true
// ''

1 && 2 && 3
// 3

4.或运算符 ||

用于多个表达式的求值。
规则是,如果第一个运算子的布尔值为true,则返回第一个运算子的值,而且不对第二个运算子求值;
如果第一个运算子的布尔值为false,则返回第二个运算子的值。

't' || '' // "t"
't' || 'f' // "t"
'' || 'f' // "f"
'' || '' // ""

短路也对这个运算符适用:

var x = 1;
true || (x = 2) // true
x // 1

第一个运算子为true,所以直接返回true,不管第二个运算子。
所以x的值没有改变,这种只通过第一个表达式的值,控制是否运行第二个表达式的机制就是短路。

或运算符可以多个连用:

false || 0 || '' || 4 || 'foo' || true
// 4

false || 0 || ''
// ''

此时返回第一个布尔值为true的表达式的值,如果所有表达式都是false,就返回最后一个表达式的值。

或运算符常用于为一个变量设置默认值:

function saveText(text) {
  text = text || '';
  // ...
}

// 或者写成
saveText(this.text || '')

如果函数调用时,没有提供参数,就默认设置为空字符串。

5.三元条件运算符 ?:

它由问号和冒号组成,分隔三个表达式。
它是JavaScript唯一一个需要三个运算子的运算符。

如果第一个表达式的布尔值是true,则返回第二个表达式的值,否则返回第三个表达式的值。

't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"

三元条件表达式与if...else语句有同样的表达效果。
但是有个重大差别,if...else是语句,没有返回值;三元条件表达式是表达式,有返回值。

所以在需要返回值的场合,只能使用三元条件表达式。

console.log(true ? 'T' : 'F');

console.log方法的参数必须是一个表达式,所以就只能使用三元条件表达式。

四、二进制位运算符

1.概述

二进制位运算符用于直接对二进制位进行计算,有七个。

这些运算符直接除以每个比特位(bit),所以是非常底层的运算,不过处理速度极快,但很不直观。

位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数再执行。

在JavaScript内部,数值都以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,而且返回值也是一个32位带符号的整数。

i = i | 0;

这行代码的意思是将i转为32位整数,不管i是整数或小数。

所以可以写出一个函数,将任何数值转为32位整数。

function toInt32(x) {
  return x | 0;
}

这个函数将任意值与0进行一次或运算,这个位运算会将一个值转为32位整数。

toInt32(1.001) // 1
toInt32(1.999) // 1
toInt32(1) // 1
toInt32(-1) // -1
toInt32(Math.pow(2, 32) + 1) // 1
toInt32(Math.pow(2, 32) - 1) // -1

对于大于或等于2的32次方的整数,大于32位的数位都会被舍去。

2.二进制或运算符

二进制或运算符|逐位比较两个运算子,两个二进制位中只要有一个为1,就返回1,否则返回0

0 | 3 // 3

0和3的二进制形式分别是0011,所以会得到11(即3)。

位运算只对整数有用,遇到小数时会将小数部分去掉。
所以将一个小数与0进行二进制或运算,相当于对该数去除小数部分,也就是取整数位。

2.9 | 0 // 2
-2.9 | 0 // -2

这种取整方法不适用于超过32位整数最大值2147483647的数。

2147483649.4 | 0;
// -2147483647

3.二进制与运算符

二进制与运算符&,规则是逐位两个运算子,两个二进制位中只要有一个位为0,就返回0,否则返回1

0 & 3 // 0

03的二进制分别是0011

4.二进制否运算符

二进制否运算符~将每个二进制位都编程相反值,10相反。

~ 3 // -4

3的32位整数形式是00000000000000000000000000000011,二进制否运算以后得到11111111111111111111111111111100。由于第一位(符号位)是1,所以这个数是一个负数。JavaScript 内部采用补码形式表示负数,即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值。这个数减去1等于11111111111111111111111111111011,再取一次反得到00000000000000000000000000000100,再加上负号就是-4

非常离谱,所以可以简单记成,一个数与自身的取反值相加,等于-1

对一个整数连用两次二进制否运算,会得到它自身。

~~3 // 3

所有的位运算都只对整数有效。二进制否运算遇到小数时,也会将小数部分舍去,只保留整数部分。所以,对一个小数连续进行两次二进制否运算,能达到取整效果。

~~2.9 // 2
~~47.11 // 47
~~1.9999 // 1
~~3 // 3

这是所有取整方法中最快的一种。

对字符串使用二进制否运算,JavaScript会先调用Number函数,将字符串转为数值。

// 相当于~Number('011')
~'011'  // -12

// 相当于~Number('42 cats')
~'42 cats' // -1

// 相当于~Number('0xcafebabe')
~'0xcafebabe' // 889275713

// 相当于~Number('deadbeef')
~'deadbeef' // -1

对于其他类型的值,也是先用Number转为数值,再处理。

// 相当于 ~Number([])
~[] // -1

// 相当于 ~Number(NaN)
~NaN // -1

// 相当于 ~Number(null)
~null // -1

5.异或运算符

异或运算符^,在两个二进制位不同时返回1,相同时返回0

0 ^ 3 // 3

0(二进制00)和3(二进制11)进行异或运算,它们每一个二进制位都不同,所以得到3(11)。

连续对两个数ab进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值。

var a = 10;
var b = 99;

a ^= b, b ^= a, a ^= b;

a // 99
b // 10

这是互换两个变量的值的最快方法。

异或运算也能用来取整。

12.9 ^ 0 // 12

6.左移运算符

左移运算符<<表示将一个数的二进制值向左移动指定的位数,尾部补0
即乘以2的指定次方。
向左移动的时候,最高位的符号位一起移动。

// 4 的二进制形式为100,
// 左移一位为1000(即十进制的8)
// 相当于乘以2的1次方
4 << 1
// 8

-4 << 1
// -8

-4的二进制形式是11111111111111111111111111111100,左移一位后得到11111111111111111111111111111000,该数转为十进制(减去1后取反,再加上负号)即为-8

如果左移0位,就相当于将该数值转为32位整数,相当于取整。

13.5 << 0
// 13

-13.5 << 0
// -13

对正负数都有用。

7.右移运算符

右移运算符>>表示将一个数的二进制值向右移动指定的位数。如果是正数,头部全部补0;如果是负数,头部全部补1。右移运算符基本上相当于除以2的指定次方(最高位即符号位参与移动)。

4 >> 1
// 2
/*
// 因为4的二进制形式为 00000000000000000000000000000100,
// 右移一位得到 00000000000000000000000000000010,
// 即为十进制的2
*/

-4 >> 1
// -2
/*
// 因为-4的二进制形式为 11111111111111111111111111111100,
// 右移一位,头部补1,得到 11111111111111111111111111111110,
// 即为十进制的-2
*/

右移运算可以模拟2的整除运算。

5 >> 1
// 2
// 相当于 5 / 2 = 2

21 >> 2
// 5
// 相当于 21 / 4 = 5

21 >> 3
// 2
// 相当于 21 / 8 = 2

21 >> 4
// 1
// 相当于 21 / 16 = 1

8.头部补0的右移运算符

头部补零的右移运算符>>>与右移运算符只有一个区别,就是一个数的二进制形式向右移动时,头部一律补零,而不考虑符号位。
所以这个运算符总是得到正值。
对于正数,运算结果与右移运算符完全一样,区别主要是负数。

4 >>> 1
// 2

-4 >>> 1
// 2147483646
/*
// 因为-4的二进制形式为11111111111111111111111111111100,
// 带符号位的右移一位,得到01111111111111111111111111111110,
// 即为十进制的2147483646。
*/

这个运算实际上是将一个值转为32位无符号整数。

查看一个负整数在计算机内部的储存形式,最快的方式就是使用这个运算符。

-1 >>> 0 // 4294967295

-1作为32位整数时,内部储存形式使用无符号整数格式解读。

9.开关作用

位运算符可以用作设置对象属性的开关。

假定某个对象有四个开关,每个开关都是一个变量。那么,可以设置一个四位的二进制数,它的每个位对应一个开关。

var FLAG_A = 1; // 0001
var FLAG_B = 2; // 0010
var FLAG_C = 4; // 0100
var FLAG_D = 8; // 1000

然后就可以用二进制与运算,检查当前设置后是否打开了指定开关。

var flags = 5; // 二进制的0101

if (flags & FLAG_C) {
  // ...
}
// 0101 & 0100 => 0100 => true

上面代码检验是否打开了开关C,如果打开则返回true,否则false

现在假设需要打开ABD三个开关,可以构造一个掩码变量。

var mask = FLAG_A | FLAG_B | FLAG_D;
// 0001 | 0010 | 1000 => 1011

上面代码对ABD三个变量进行二进制或运算,得到掩码值为二进制的1011

有了掩码,二进制或运算就可以确保打开指定的开关。

flags = flags | mask;

这代表三个开关的二进制位都打开了。

五、其他运算符与运算顺序

1.void运算符

这个运算符的作用是执行一个表达式,然后什么都不返回,或者说返回undefined

void 0 // undefined
void(0) // undefined

最好使用后一种写法,因为void运算符的优先性很高,如果不用括号,很危险。
比如void 4 + 7实际上等同于(void 4) + 7

下面是一个例子。

var x = 3;
void (x = 5) //undefined
x // 5

这个运算符的主要用途是浏览器的书签工具(Bookmarklet),以及在超级链接中插入代码防止网页跳转。

<script>
function f() {
  console.log('Hello World');
}
</script>
<a href="http://example.com" onclick="f(); return false;">点击</a>

点击链接后,先执行onclick的代码,由于它返回false,所以浏览器不会跳转。
void可以取代上面的写法。

<a href="javascript: void(f())">文字</a>

下面的例子是,用户点击链接提交表单,但是不产生页面跳转。

<a href="javascript: void(document.form.submit())">
  提交
</a>

2.逗号运算符

用于对两个表达式求值,返回后一个表达式的值。

'a', 'b' // "b"

var x = 0;
var y = (x++, 10);
x // 1
y // 10

这个运算符的一个用途是,在返回一个值之前,进行一些辅助操作。

var value = (console.log('Hi!'), true);
// Hi!

value // true

上面代码中,先执行逗号前面的操作,然后返回逗号后的值。

3.运算顺序

①.优先级

各种运算符的优先级是不一样的,优先级高的先执行,低的后执行。

4 + 5 * 6 // 34

乘法运算符*的优先级高于加法运算符+,所以先乘。

4 + (5 * 6) // 34

相当于这样。

②.圆括号

圆括号可以用来提升运算的优先级,因为它的优先级最高,即圆括号里的表达式会第一个运算。

(4 + 5) * 6 // 54

圆括号不是运算符,而是一种语法结构,有两种用法:一种是提升运算的优先级;一种是调用函数。

如果整个表达式都放在圆括号之中,就不会有任何效果。

(expression)
// 等同于
expression

如果函数放在圆括号里,会返回函数本身。
如果圆括号跟在函数后面,就是调用函数。

function f() {
  return 1;
}

(f) // function f(){return 1;}
f() // 1

圆括号中只能放表达式,如果放语句,就会报错。

(var a = 1)
// SyntaxError: Unexpected token var

③.左结合与右结合

a OP b OP c

上面代码中,OP表示运算符,它可以有两种解释方式。

// 方式一
(a OP b) OP c

// 方式二
a OP (b OP c)

方式一是将左侧两个运算数结合在一起,采用这种解释方式的运算符,称为“左结合”(left-to-right associativity)运算符;方式二是将右侧两个运算数结合在一起,这样的运算符称为“右结合”运算符(right-to-left associativity)。

JavaScript的大多数运算符的左结合。

x + y + z

// 引擎解释如下
(x + y) + z

少数运算符是右结合,其中最主要的是赋值运算符和三元条件运算符。

w = x = y = z;
q = a ? b : c ? d : e ? f : g;

解释如下:

w = (x = (y = z));
q = a ? b : (c ? d : (e ? f : g));

指数运算符**也是右结合。

2 ** 3 ** 2
// 相当于 2 ** (3 ** 2)
// 512

总结

没了。

标签:false,运算子,二进制,灵气,滤管,运算符,var,true,梦路
来源: https://blog.csdn.net/qq_43332029/article/details/117517325