JavaScript 算術(shù)運(yùn)算符

2023-03-20 15:57 更新

概述

運(yùn)算符是處理數(shù)據(jù)的基本方法,用來(lái)從現(xiàn)有的值得到新的值。JavaScript 提供了多種運(yùn)算符,覆蓋了所有主要的運(yùn)算。

JavaScript 共提供10個(gè)算術(shù)運(yùn)算符,用來(lái)完成基本的算術(shù)運(yùn)算。

  • 加法運(yùn)算符x + y
  • 減法運(yùn)算符x - y
  • 乘法運(yùn)算符x * y
  • 除法運(yùn)算符x / y
  • 指數(shù)運(yùn)算符x ** y
  • 余數(shù)運(yùn)算符x % y
  • 自增運(yùn)算符++x 或者 x++
  • 自減運(yùn)算符--x 或者 x--
  • 數(shù)值運(yùn)算符+x
  • 負(fù)數(shù)值運(yùn)算符-x

減法、乘法、除法運(yùn)算法比較單純,就是執(zhí)行相應(yīng)的數(shù)學(xué)運(yùn)算。下面介紹其他幾個(gè)算術(shù)運(yùn)算符,重點(diǎn)是加法運(yùn)算符。

加法運(yùn)算符

基本規(guī)則

加法運(yùn)算符(+)是最常見(jiàn)的運(yùn)算符,用來(lái)求兩個(gè)數(shù)值的和。

1 + 1 // 2

JavaScript 允許非數(shù)值的相加。

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

上面代碼中,第一行是兩個(gè)布爾值相加,第二行是數(shù)值與布爾值相加。這兩種情況,布爾值都會(huì)自動(dòng)轉(zhuǎn)成數(shù)值,然后再相加。

比較特殊的是,如果是兩個(gè)字符串相加,這時(shí)加法運(yùn)算符會(huì)變成連接運(yùn)算符,返回一個(gè)新的字符串,將兩個(gè)原字符串連接在一起。

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

如果一個(gè)運(yùn)算子是字符串,另一個(gè)運(yùn)算子是非字符串,這時(shí)非字符串會(huì)轉(zhuǎn)成字符串,再連接在一起。

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

加法運(yùn)算符是在運(yùn)行時(shí)決定,到底是執(zhí)行相加,還是執(zhí)行連接。也就是說(shuō),運(yùn)算子的不同,導(dǎo)致了不同的語(yǔ)法行為,這種現(xiàn)象稱(chēng)為“重載”(overload)。由于加法運(yùn)算符存在重載,可能執(zhí)行兩種運(yùn)算,使用的時(shí)候必須很小心。

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

上面代碼中,由于從左到右的運(yùn)算次序,字符串的位置不同會(huì)導(dǎo)致不同的結(jié)果。

除了加法運(yùn)算符,其他算術(shù)運(yùn)算符(比如減法、除法和乘法)都不會(huì)發(fā)生重載。它們的規(guī)則是:所有運(yùn)算子一律轉(zhuǎn)為數(shù)值,再進(jìn)行相應(yīng)的數(shù)學(xué)運(yùn)算。

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

上面代碼中,減法、除法和乘法運(yùn)算符,都是將字符串自動(dòng)轉(zhuǎn)為數(shù)值,然后再運(yùn)算。

對(duì)象的相加

如果運(yùn)算子是對(duì)象,必須先轉(zhuǎn)成原始類(lèi)型的值,然后再相加。

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

上面代碼中,對(duì)象obj轉(zhuǎn)成原始類(lèi)型的值是[object Object],再加2就得到了上面的結(jié)果。

對(duì)象轉(zhuǎn)成原始類(lèi)型的值,規(guī)則如下。

首先,自動(dòng)調(diào)用對(duì)象的valueOf方法。

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

一般來(lái)說(shuō),對(duì)象的valueOf方法總是返回對(duì)象自身,這時(shí)再自動(dòng)調(diào)用對(duì)象的toString方法,將其轉(zhuǎn)為字符串。

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

對(duì)象的toString方法默認(rèn)返回[object Object],所以就得到了最前面那個(gè)例子的結(jié)果。

知道了這個(gè)規(guī)則以后,就可以自己定義valueOf方法或toString方法,得到想要的結(jié)果。

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

obj + 2 // 3

上面代碼中,我們定義obj對(duì)象的valueOf方法返回1,于是obj + 2就得到了3。這個(gè)例子中,由于valueOf方法直接返回一個(gè)原始類(lèi)型的值,所以不再調(diào)用toString方法。

下面是自定義toString方法的例子。

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

obj + 2 // "hello2"

上面代碼中,對(duì)象objtoString方法返回字符串hello。前面說(shuō)過(guò),只要有一個(gè)運(yùn)算子是字符串,加法運(yùn)算符就變成連接運(yùn)算符,返回連接后的字符串。

這里有一個(gè)特例,如果運(yùn)算子是一個(gè)Date對(duì)象的實(shí)例,那么會(huì)優(yōu)先執(zhí)行toString方法。

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

obj + 2 // "hello2"

上面代碼中,對(duì)象obj是一個(gè)Date對(duì)象的實(shí)例,并且自定義了valueOf方法和toString方法,結(jié)果toString方法優(yōu)先執(zhí)行。

余數(shù)運(yùn)算符

余數(shù)運(yùn)算符(%)返回前一個(gè)運(yùn)算子被后一個(gè)運(yùn)算子除,所得的余數(shù)。

12 % 5 // 2

需要注意的是,運(yùn)算結(jié)果的正負(fù)號(hào)由第一個(gè)運(yùn)算子的正負(fù)號(hào)決定。

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

所以,為了得到負(fù)數(shù)的正確余數(shù)值,可以先使用絕對(duì)值函數(shù)。

// 錯(cuò)誤的寫(xiě)法
function isOdd(n) {
  return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false

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

余數(shù)運(yùn)算符還可以用于浮點(diǎn)數(shù)的運(yùn)算。但是,由于浮點(diǎn)數(shù)不是精確的值,無(wú)法得到完全準(zhǔn)確的結(jié)果。

6.5 % 2.1
// 0.19999999999999973

自增和自減運(yùn)算符

自增和自減運(yùn)算符,是一元運(yùn)算符,只需要一個(gè)運(yùn)算子。它們的作用是將運(yùn)算子首先轉(zhuǎn)為數(shù)值,然后加上1或者減去1。它們會(huì)修改原始變量。

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

--x // 1
x // 1

上面代碼的變量x自增后,返回2,再進(jìn)行自減,返回1。這兩種情況都會(huì)使得,原始變量x的值發(fā)生改變。

運(yùn)算之后,變量的值發(fā)生變化,這種效應(yīng)叫做運(yùn)算的副作用(side effect)。自增和自減運(yùn)算符是僅有的兩個(gè)具有副作用的運(yùn)算符,其他運(yùn)算符都不會(huì)改變變量的值。

自增和自減運(yùn)算符有一個(gè)需要注意的地方,就是放在變量之后,會(huì)先返回變量操作前的值,再進(jìn)行自增/自減操作;放在變量之前,會(huì)先進(jìn)行自增/自減操作,再返回變量操作后的值。

var x = 1;
var y = 1;

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

上面代碼中,x是先返回當(dāng)前值,然后自增,所以得到1y是先自增,然后返回新的值,所以得到2。

數(shù)值運(yùn)算符,負(fù)數(shù)值運(yùn)算符

數(shù)值運(yùn)算符(+)同樣使用加號(hào),但它是一元運(yùn)算符(只需要一個(gè)操作數(shù)),而加法運(yùn)算符是二元運(yùn)算符(需要兩個(gè)操作數(shù))。

數(shù)值運(yùn)算符的作用在于可以將任何值轉(zhuǎn)為數(shù)值(與Number函數(shù)的作用相同)。

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

上面代碼表示,非數(shù)值經(jīng)過(guò)數(shù)值運(yùn)算符以后,都變成了數(shù)值(最后一行NaN也是數(shù)值)。具體的類(lèi)型轉(zhuǎn)換規(guī)則,參見(jiàn)《數(shù)據(jù)類(lèi)型轉(zhuǎn)換》一章。

負(fù)數(shù)值運(yùn)算符(-),也同樣具有將一個(gè)值轉(zhuǎn)為數(shù)值的功能,只不過(guò)得到的值正負(fù)相反。連用兩個(gè)負(fù)數(shù)值運(yùn)算符,等同于數(shù)值運(yùn)算符。

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

上面代碼最后一行的圓括號(hào)不可少,否則會(huì)變成自減運(yùn)算符。

數(shù)值運(yùn)算符號(hào)和負(fù)數(shù)值運(yùn)算符,都會(huì)返回一個(gè)新的值,而不會(huì)改變?cè)甲兞康闹怠?/p>

指數(shù)運(yùn)算符

指數(shù)運(yùn)算符(**)完成指數(shù)運(yùn)算,前一個(gè)運(yùn)算子是底數(shù),后一個(gè)運(yùn)算子是指數(shù)。

2 ** 4 // 16

注意,指數(shù)運(yùn)算符是右結(jié)合,而不是左結(jié)合。即多個(gè)指數(shù)運(yùn)算符連用時(shí),先進(jìn)行最右邊的計(jì)算。

// 相當(dāng)于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512

上面代碼中,由于指數(shù)運(yùn)算符是右結(jié)合,所以先計(jì)算第二個(gè)指數(shù)運(yùn)算符,而不是第一個(gè)。

賦值運(yùn)算符

賦值運(yùn)算符(Assignment Operators)用于給變量賦值。

最常見(jiàn)的賦值運(yùn)算符,當(dāng)然就是等號(hào)(?=?)。

// 將 1 賦值給變量 x
var x = 1;

// 將變量 y 的值賦值給變量 x
var x = y;

賦值運(yùn)算符還可以與其他運(yùn)算符結(jié)合,形成變體。下面是與算術(shù)運(yùn)算符的結(jié)合。

// 等同于 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

下面是與位運(yùn)算符的結(jié)合(關(guān)于位運(yùn)算符,請(qǐng)見(jiàn)后文的介紹)。

// 等同于 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

這些復(fù)合的賦值運(yùn)算符,都是先進(jìn)行指定運(yùn)算,然后將得到值返回給左邊的變量。


以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)