"Code tailor",为前端开发者提供技术相关资讯以及系列基础文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。
前言
在开始学习之前,我们想要告诉您的是,本文章是对 JavaScript
语言知识中 "操作符" 部分的总结,如果您已掌握下面知识事项,则可跳过此环节直接进入题目练习
- 一元操作符
- 位操作符(了解)
- 布尔操作符
- 乘性操作符
- 指数操作符
- 加性操作符
- 关系操作符
- 相等操作符
- 条件操作符
- 赋值操作符
- 逗号操作符
- 运算顺序
如果您对某些部分有些遗忘,👇🏻 已经为您准备好了!
什么是操作符 ?
在 ECMA-262 中描述了一组可用于操作数据值的符号被称为操作符
有哪些类型的操作符
一元操作符
只操作一个值的操作符叫一元操作符
1.递增/递减操作符
- 递增操作符
有两种形式,即 ++i
和 i++
(两者有些略微区别)
let age = 29
++age
实际上等于
let age = 29
age = age + 1 //console.log(age) = 30
i++ 和 ++i 的区别
- i++ :先引用后自加
- ++i :先自加后引用
- 递减操作符
同理 i--
和 --i
也有略微区别
let age = 29
--age //console.log(age) = 28
let num = 2
let num1 = 20
let sum = num-- + num1 //console.log(sum) = 22;
// 如果换成这样
let sum = --num + num1 //console.log(sum) = 21;
注意: 该操作符可以作用于任何值,不限于整数 — 字符串、布尔值、浮点值、甚至对象都可以。
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变成数值。
- 对于字符串,如果不是有效的数值形式,则将变量的值设置为
NaN
。变量类型从字符串变成数值。 - 对于布尔值,如果是
false
,则转换为0
再应用改变。变量类型从布尔值变成数值。 - 对于布尔值,如果是
true
,则转换为1
再应用改变。变量类型从布尔值变成数值。 - 对于浮点值,加
1
或减1
。 - 如果是对象,则调用其
valueOf()
方法取得可以操作的值。对得到的值应用上述规则。如果是NaN
,则调用toString()
并再次应用其他规则。变量类型从对象变成数值。
2.一元加和减
一元加和减操作符对大多数开发者来说并不陌生,它们在 ECMAScript
中跟在高中数学中的用途一样。
- 一元加:由一个加号(
+
)表示,放在变量前头,对数值没有任何影响
let num = 25
num = +num
console.log(num) // 25
若应用到非数值,则会执行与使用 Number()
转型函数一样的类型转换;
注意:
- 布尔值
false
和true
转换为 0 和 1 - 字符串根据特殊规则进行解析
- 对象会调用它们的
valueOf()
和(或)toString()
方法以得到可以转换的值
let a = '01'
let b = '1.2'
let c = 'c'
let d = false
let e = 1.2
a = +a // 变为数值1
b = +b // 变为数值1.2
c = +c // 变为NaN
d = +d // 变为数值0
e = +e // 不变
- 一元减: 由一个减号(
-
)表示,放在变量前头,主要用于把数值变成负值,如把 1 转换为 -1。
let num = 25
num = -num
console.log(num) // -25
若应用到非数值,一元减会遵循与一元加同样的规则,先对它们进行转换,然后再取负值
let a = '01'
let b = '1.2'
let c = 'c'
let d = false
let e = 1.2
a = -a // 变为数值-1
b = -b // 变为数值-1.2
c = -c // 变为NaN
d = -d // 变为数值0
e = -e // 变为-1.2
位操作符(了解)
用于数值的底层操作,也就是操作内存中表示数据的比特(位)
1.按位非
按位非操作符用波浪符(~)表示,它的作用是返回数值的一补数
let num1 = 25 // 二进制 00000000000000000000000000011001
let num2 = ~num1 // 二进制 11111111111111111111111111100110
console.log(num2) // -26
2.按位与
按位与就是将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的与操作
let result = 27 & 4
console.log(result) // 0
/*
27 = 0000 0000 0000 0000 0000 0000 0001 1011
4 = 0000 0000 0000 0000 0000 0000 0000 0100
---------------------------------------------
AND = 0000 0000 0000 0000 0000 0000 0000 0000
*/
3.按位或
按位或操作符用管道符(|)表示,同样有两个操作数,按位或遵循真值表
let result = 27 | 4
console.log(result) // 31
/*
27 = 0000 0000 0000 0000 0000 0000 0001 1011
4 = 0000 0000 0000 0000 0000 0000 0000 0100
---------------------------------------------
OR = 0000 0000 0000 0000 0000 0000 0001 1111
*/
4.按异位或
按位异或用脱字符(^)表示,同样有两个操作数,按位异或遵循真值表
let result = 27 ^ 3
console.log(result) // 24
/*
27 = 0000 0000 0000 0000 0000 0000 0001 1011
3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0001 1000
*/
5.左移
左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动
let oldValue = 2 // 等于二进制 10
let newValue = oldValue << 5 // 等于二进制 1000000,即十进制 64
注意在移位后,数值右端会空出 5 位。左移会以 0 填充这些空位,让结果是完整的 32 位数值,左移会保留它所操作数值的符号
6.有符号右移
有符号右移由两个大于号(>>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。有符号右移实际上是左移的逆运算
let oldValue = 64 // 等于二进制 1000000
let newValue = oldValue >> 5 // 等于二进制 10,即十进制 2
7.无符号右移
无符号右移用 3 个大于号表示(>>>),会将数值的所有 32 位都向右移。对于正数,无符号右移与有符号右 移结果相同
let oldValue = 64 // 等于二进制 1000000
let newValue = oldValue >> 5 // 等于二进制 10,即十进制 2
对于负数,有时候差异会非常大。与有符号右移不同,无符号右移会给空位补 0,而不管符号位是什么。
let oldValue = -64 // 等于二进制 11111111111111111111111111000000
let newValue = oldValue >>> 5 // 等于十进制 134217726
/*
11111111111111111111111111000000 => 等于-64
00000111111111111111111111111110 => 等于134217726
*/
布尔操作符
1.逻辑非
操作数 | 返回值 |
---|---|
对象 | false |
空字符串 | true |
非空字符串 | false |
数值 0 | true |
非 0 数值(包括 Infinity) | false |
null | true |
NaN | true |
undefined | true |
console.log(!false) // true
console.log(!'blue') // false
console.log(!0) // true
console.log(!NaN) // true
console.log(!'') // true
console.log(!12345) // false
2.逻辑与
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
对象 | any | 返回第二个操作数 |
true | 对象 | 返回第二个操作数 |
对象 | 对象 | 返回第二个操作数 |
null | any | 如果有一个操作数是 null,则返回 null |
NaN | any | 如果有一个操作数是 NaN,则返回 NaN |
undefined | any | 如果有一个操作数是 undefined,则返回 undefined |
let found = true;
let clear = {};
let result = (found && clear); // 返回clear
3.逻辑或
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
对象 | any | 如果第一个操作数是对象,则返回第一个操作数 |
false | 对象 | 如果第一个操作数求值为 false,则返回第二个操作数 |
对象 | 对象 | 如果两个操作数都是对象,则返回第一个操作数 |
null | null | 如果两个操作数都是 null,则返回 null |
NaN | NaN | 如果两个操作数都是 NaN,则返回 NaN |
undefined | undefined | 如果两个操作数都是 undefined,则返回 undefined |
let myObject = preObject || afeObject
preObject
变量包含首选的值,afeObject
变量包含备用的值
- 如果
preObject
不是null
,则它的值就会赋给myObject
; - 如果
preObject
是null
,则afeObject
的值就会赋给myObject
。 - 这种模式在
ECMAScript
代码中经常用于变量赋值
乘性操作符
ECMAScript
定义了 3 个乘性操作符:乘法、除法和取模
1.乘法操作符
乘法操作符由一个星号(*)表示,可以用于计算两个数值的乘积。其语法类似于 C 语言
let result = 12 * 34
注意:
返回 NaN 的操作情况 | 返回 Infinity 的操作情况 |
---|---|
有任一操作数是 NaN | Infinity 乘以 Infinity |
Infinity 乘以 0 | Infinity 乘以非 0 的有限数值,则根据第二个操作数的符号返回 Infinity 或-Infinity |
2.除法操作符
除法操作符由一个斜杠(/)表示,用于计算第一个操作数除以第二个操作数的商
let result = 34 / 12
注意:
操作数 | 结果 |
---|---|
有任一操作数是 NaN | NaN |
Infinity 除以 Infinity | NaN |
是 0 除以 0 | NaN |
非 0 的有限值除以 0 | 根据第一个操作数的符号返回 Infinity 或-Infinity |
Infinity 除以任何数值 | 根据第二个操作数的符号返回 Infinity 或-Infinity |
3.取模操作符
取模(余数)操作符由一个百分比符号(%)表示
let result = 16 % 5 //余1个
操作数 | 返回值 |
---|---|
数值 | 余数 |
如果被除数是无限值,除数是有限值 | NaN |
如果被除数是有限值,除数是 0 | NaN |
如果是 Infinity 除以 Infinity | NaN |
如果被除数是有限值,除数是无限值 | 被除数 |
如果被除数是 0,除数不是 0 | 0 |
如果有不是数值的操作数,则先在后台用 Number()函数将其转换为数值 | / |
指数操作符
ECMAScript 7
新增了指数操作符(**),Math.pow()
现在有了自己的操作符,结果是一样的
console.log(Math.pow(4, 2); // 16
console.log(4 ** 2); // 9
console.log(Math.pow(16, 0.5); // 4
console.log(16 ** 0.5); // 4
加性操作符
加性操作符,即加法和减法操作符,一般都是编程语言中最简单的操作符
1.加法操作符
第一操作数 | 第二操作数 | 返回值 |
---|---|---|
数值 | NaN | NaN |
Infinity | Infinity | Infinity |
-Infinity | -Infinity | -Infinity |
Infinity | -Infinity | NaN |
+0 | +0 | +0 |
-0 | +0 | +0 |
-0 | -0 | -0 |
字符串 | 字符串 | 拼接起来 |
字符串 | any | 将第二操作数转换为字符,再与第一操作数拼接起来 |
注:第一操作数和第二操作数无特定顺序
let result = 10 + 10 // 20
let result2 = 10 + '5' // 105
2.减法操作符
第一操作数 | 第二操作数 | 返回值 |
---|---|---|
数值 | NaN | NaN |
Infinity | Infinity | NaN |
-Infinity | -Infinity | NaN |
Infinity | -Infinity | Infinity |
-Infinity | Infinity | -Infinity |
+0 | +0 | +0 |
-0 | +0 | -0 |
-0 | -0 | +0 |
补充:如果有任一操作数是字符串、布尔值、null
或 undefined
,则先在后台使用 Number()
将其转换为数值,然后再根据前面的规则执行数学运算
let result1 = 6 - true // true 被转换为 1,所以结果是 5
let result2 = NaN - 2 // NaN
let result3 = 6 - 3 // 3
let result4 = 6 - '' // ""被转换为 0,所以结果是 6
let result5 = 3 - '2' // "2"被转换为 2,所以结果是 1
let result6 = 2 - null // null 被转换为 0,所以结果是 2
关系操作符
关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),用法跟数学课上学的一样
let result1 = 6 > 3 // true
let result2 = 4 < 3 // false
操作数 | 发生行为 |
---|---|
都是数值 | 数值比较 |
都是字符串 | 逐个比较字符串中对应字符的编码 |
任一操作数是数值 | 则将另一个操作数转换为数值,执行数值比较 |
任一操作数是对象 | 调用其 valueOf()方法,如果没有 valueOf()方法,则调用 toString()方法,取得结果后再根据前面的规则执行比较 |
任一操作数是布尔值 | 将其转换为数值再执行比较 |
//补充:
let result1 = NaN < 5 // false
let result2 = NaN >= 5 // false
相等操作符
判断两个变量是否相等是编程中最重要的操作之一
ECMAScript
提供了两组操作符。第一组是等于和不等于,它们在比较之前执行转换。第二组是全等和不全等,它们,在比较之前不执行转换。
1.等于和不等于
等于操作符用两个等于号(==)表示,如果操作数相等,则会返回 true
不等于操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回 true
操作数 | 发生行为 |
---|---|
任一操作数是布尔值 | 将其转换为数值再比较是否相等(false :0 true :1) |
字符串+数值 | 尝试将字符串转换为数值,再比较是否相等 |
一个操作数是对象,另一个操作数不是 | 调用对象的 valueOf()方法取得其原始值,再根据之前规则比较 |
任一操作数是 NaN | 相等操作符返回 false,不相等操作符返回 true |
两个操作数都是对象 | 比较它们是否指向同一个对象 |
补充:(1)NaN
不等于 NaN
(2)null
和 undefined
相等
(3)null
和 undefined
不能转换为其他类型的值再进行比较
2.全等和不全等
全等和不全等操作符需在比较数在不转换的前提下全等或不全等才返回 true
let result1 = '34' == 34 // true,转换后相等
let result2 = '34' === 34 // false,不相等,因为数据类型不同
let result1 = '23' != 23 // false,转换后相等
let result2 = '23' !== 23 // true,不相等,因为数据类型不同
let result1 = null == undefined // true
let result1 = null === undefined // false,不是相同的数据类型
条件操作符
条件操作符是 ECMAScript 中用途最为广泛的操作符之一
let min = num1 < num2 ? num1 : num2
//如果 num1 小于 num2 ,则返回num1 ,否则返回num2
赋值操作符
简单赋值用等于号(=)表示,将右手边的值赋给左手边的变量
let num = 100
每个数学操作符以及其他一些操作符都有对应的复合赋值操作符
乘后除值 | *= |
---|---|
除后赋值 | /= |
取模后赋值 | %= |
加后赋值 | += |
减后赋值 | -= |
左移后赋值 | <<= |
右移后赋值 | \>>= |
无符号右移后赋值 | \>>>= |
逗号操作符
逗号操作符可以用来在一条语句中执行多个操作
let num0 = 1,
num1 = 2,
num2 = 3
运算顺序
1.优先级
JavaScript 各种运算符的优先级别(Operator Precedence)是不一样的。优先级高的运算符先执行,优先级低的运算符后执行。
3 + 1 * 2 // 6
在上段代码中,乘法运算符( *
)的优先级高于加法运算符( +
),所以先执行乘法,后执行加法。
这是一个很简单的优先级问题,但如果多个运算符混写在一起,常常会令人困惑。
var x = 1
var array = []
var y = array.length <= 0 || array[0] === undefined ? x : array[0]
优先级 |
---|
小于等于(<=) |
严格相等(===) |
或(|| ) |
三元(?:) |
等号(=) |
//因此上述代码实际运算是这样的
var y = array.length <= 0 || array[0] === undefined ? x : array[0]
注:记住所有运算符的优先级是没必要的,用到时查询就好。
2.左结合和右结合
对于优先级别相同的运算符,大多数情况,计算顺序总是从左到右,这叫做运算符的“左结合”(left-to-right associativity),即从左边开始计算。
a + b + c
像这种很简单就是先计算左边 a
与 b
的和,再计算与 c
的和
但有一些运算符的计算顺序是从右到左,即从右边开始计算,这叫做运算符的"右结合"。主要有赋值运算符(=
)和三元条件运算符( ?:
)
h = x = y = z
i = a ? b : c ? d : e ? f : g
// <==等价于==>
h = x = y = z
i = a ? b : c ? d : e ? f : g
题目自测:
1: 下面代码输出什么 ?
;+true
!'Lydia'
- A:
1
andfalse
- B:
false
andNaN
- C:
false
andfalse
2: 下面代码输出什么 ?
function sum(a, b) {
return a + b
}
sum(1, '2')
- A.
NaN
- B.
TypeError
- C.
"12"
- D.
3
3: 下面代码输出什么 ?
!!null
!!''
!!1
- A.
false
true
false
- B.
false
false
true
- C.
false
true
true
- D.
true
true
false
4: 下面代码输出什么 ?
console.log(3 + 4 + '5')
- A.
"345"
- B.
"75"
- C.
12
- D.
"12"
题目解析
一、
Answer: A
+
号运算符将 true
转换为 Number
类型 1
而 string
类型 Lydia
转化为 Boolean
值为 true
,而前面有 !
,故返回 false
二、
Answer: C
当 +
运算符碰到数值与字符串相加时,将数值转化为字符串,再拼接
三、
Answer: B
null
是 false
. !null
返回 true
. !true
返回 false
.
""
是 true
. !""
返回 true
. !true
返回 false
.
1
是 true
. !1
返回 false
. !false
返回 true
.
四、
Answer: B
运算符关联性是编译器计算表达式的顺序,从左到右或从右到左。只有当所有运算符具有相同的优先级时,才会发生这种情况。我们只有一种运算符:+
。此外,关联性是从左到右的。
先运算 3+4。结果是数字 7。
7+“5”隐式转化为“75”。JavaScript
将数字 7 转换为字符串,我们可以使用 +
运算符连接两个字符串。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。