这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
运算符是解决数据运算的问题
操作符和操作数
操作符: 运输符,参与运算的符号
操作数: 参与运算的数据,也称之为”元”.
操作符不一定只有一个符合,操作符出现的问题不同,可能具有不同的含义。
1 + 3 // 这里的 + 代表的是将 1 和 3 进行相加
+1.3 // 这里的 + 代表1.3是整数
复制代码
常用操作符
操作符 | 意义 |
---|---|
= |
赋值符号,将右边的数据赋值给左边 |
. |
访问符号,用于访问对象的属性 |
[] |
访问符号(对象表达式),用于访问对象的属性 |
() |
函数调用或者改变运算顺序 |
运算符分类
按照操作数数量区分:
- 一元(目)运算符:
()
、.
、[]
、++
、--
- 二元(目)运算符:
+
、-
、/
、*
、%
、=
- 三元(目)运算符:
? :
现代大部分浏览器控制台的环境是
REPL
(Read Eval Print Loop)环境,实时的输入输出环境
算术运算符
算数运算符是用来做数学运算的符号,如:
+ - * / %
等
注意事项
1. 在js中,小数的运算是不精确的。如:
2. 在js中除数为0:
- 如果被除数为正数,得到 Infinity.
- 如果被除数为负数,得到 -Infinity
- 如果除数和被除数都是0,得到 NaN(Not a Number)
3. 求模运算
结果的符号取决于被除数。如:
4. 隐式类型Number
转换
boolean
: true —> 1, false —> 0
string
: 如果内部的数据是一个正确的数字,直接去掉首位空格转换成数字,如果是其他字符串除了Infinity
这个关键字外的都直接转成NaN。
null
: null —> 0
undefined
: undefined —> NaN
object
: object —-> ‘[object Object]’ —-> NaN, 但是有一个特殊,如果是数组的话,是 0
function
: function —-> NaN
5. 加号运算符
如果加号运算符是使用在第四条的表达式前面,将会调用 Number的隐士转换。
只要任何一边是字符串,那么就作为连接符来使用
自增(++)
和自减(--)
++
: 将自身的值进行加1--
: 将自身的值进行减1
注意事项
自增和自减的优先级特别高,算术运算中的运算顺序如下:
++, -- >
* / %>
+ – >=
x++
: 将变量x自增1,得到的表达式的值是自增之前的值。
++x
: 将变量x自增1,得到的表达式的值是自增之后的值。
-
x--
: 将变量x自减1,得到的表达式的值是自减之前的值。 -
--x
: 将变量x自减1,得到的表达式的值是自减之后的值。 -
优先级运算的细节
- 从左往右依次查看
- 如果遇到操作数,将数据直接取出
- 如果遇到相邻的两个运算符,并且左边的运算符优先级大于右边的运算符,则直接运行左边的运算符,否则运算右边的运算符。
金典面试题
先来一道简单的
var x = 1;
console.log(x + x++ + ++x);
复制代码
题目解析如下:
var x = 1;
x + x ++ + ++x
第一步: + 的运算符顺序小于 ++ ,先计算 x++, 但是x ++ 是自增之前的值,
x = 2
1 + 1 + ++x
第二步: + 和 + 的运算顺序相同,从左往右
x = 2
2 + ++ x
第三步: + 的运算顺序小于 ++,先算++并且是自增之后的值
x = 3
2 + 3
最后结果就是 5
复制代码
来一道复杂点的
var x = 1;
console.log(x + x++ * ++x * (x = x ++ + x + ++x) * ++x + ++x);
复制代码
题目解析如下:
这道题目含有小括号,我们只是需要把小括号看成一个整体,但是运算顺序还是从左往右。
x = 1
x + x++ * ++x * (x = x ++ + x + ++x) * ++x + ++x
x = 1
第一步: 从左往右, + 的运算符小于 ++ 的,所以先算 x++,x ++ 是自增之前的值。并且把第一位给赋值
x = 2
1 + 1 * ++x * (x = x ++ + x + ++x) * ++x + ++x
第二步: + 和 *做比较, * 的优先级高,算后面的。 * 和 ++的优先级是 ++的高,需要先算 ++x,自增之后的值
x = 3
1 + 1 * 3 * (x = x ++ + x + ++x) * ++x + ++x
第三步: * 和 * 的优先级一样,先算前面的 *
x = 3
1 + 3 * (x = x ++ + x + ++x) * ++x + ++x
第四步: + 和 * 的优先级是 *的高,需要把括号看成一个整体,先算括号里面的结果。括号中的 = 和 ++ 是 ++的优先级高,先算括号中的 x++, 先自增然后取自增之前的值。
x = 4
1 + 3 * (x = 3 + x + ++x) * ++x + ++x
第五步: 4后面的 + 和 + 优先级一样,计算前面的 +
x = 4
1 + 3 * (x = 7 + ++x) * ++x + ++x
第六步: 计算括号中的 ++x,自增后取后面的值,然后最后赋值x
x= 12
1 + 3 * 12 * ++x + ++x
第七步: * 与 *的优先级一样,计算前面的*
x= 12
1 + 36 * ++x + ++x
第八步: * 与 ++的优先级是 ++x更高,先计算 ++x,自增取之后的值
x= 13
1 + 39 * 13 + ++x
第九步: + 与 * 是*的优先级高
x= 13
469 + ++x
第十步: 计算后面的 ++
x= 13
469 + 14
483
复制代码
比较运算符
比较运算符分为: 大小比较: > < >= <=
, 相等比较: == != === !==
,
- 比较运算符的返回类型是
boolean
- 算术运算符的优先级大于比较运算符
大小比较注意事项
- 两个字符串大小比较是依次进行比较
ASCII
console.log('11' > '2') // false
复制代码
- 如果两个数据是原始类型(只要一个不是字符串),将会对数据调用
Number
进行转换。(NaN与任何数据进行比较,得到的都是false
)
- 如果其中数据是引用类型,需要将引用类型转成原始类型,然后来进行比较.
相等比较注意事项
==
比较两个数据是否相等,!=
比较两个数据不相等
- 左右两端的数据类型相同,直接比较两个数据本身是否相同(引用类型比较的是引用的地址)
- 两端数据不相同
null
和undefined
, 他们直接相等,和其他原始类型比较,不相等
- NaN 与任何值比较,都是
false
, Infinity 只等于它自身
- 引用类型和原始类型比较, 引用类型需要转换成原始类型进行比较。
- 其他原始类型,比较时候会自动调用
Number
来 进行转换
由于
== !=
比较会有比较多奇葩问题,在开发中,我们一般使用 严格比较=== !==
===
(严格相等) 两端的数据类型必须一致就返回true
, 否则为false
!==
(严格不相等) 两端的数据类型不一致就返回true
, 否则为false
逻辑运算符
逻辑运算符(布尔运算符)包含以下:
&&, ||, !
,以下数据判断均为false
:null
,undefined
,false
,NaN
,''
,0
与(并且)
符号: &&
**语法: **
表达式1 && 表达式2 && ...
复制代码
表达的意思是,将表达式1进行boolean
判定,如果为表达式1为真返回表达式2的结果, 如果为表达式1为假直接返回表达式1,不执行表达式2.
或
符号
||
**语法: **
表达式1 || 表达式2 || ...
复制代码
表达的意思是,将表达式1进行boolean
判定,如果为表达式1为假直接返回表达式1,不执行表达式2,如果为表达式1为真返回表达式2的结果
非
符号
!
**语法: **
!表达式
复制代码
表达式的意思是取反,返回的结果一定是 boolean
三目运算符
**语法: **
表达式1 ? 表达式2 : 表达式3
复制代码
意思是对表达式1进行boolean
判定,如果为真返回 表达式2, 否则返回表达式3
复合的赋值运算符
除了
=
是赋值运算符外,还有其他赋值的运算符
var x = 1;
复制代码
+=
(加等于): x += 1 等同于 x = x + 1;-=
(减等于): x -= 1 等同于 x = x – 1;*=
(乘等于): x *= 10 + 1 等同于 x = x * (10 + 1);/=
(除等于): x /= 10 + 1 等同于 x = x / (10 + 1);%=
(模等于): x %= 10 + 1 等同于 x = x % (10 + 1);
void 运算符
void 运算符是一个一元运算符。作用是:运行表达式,返回一个
undefined
语法
void 表达式
void(表达式)
复制代码
这个运算符类似于 typeof ,有两种写法。
逗号运算符
依次运算多个表达式,返回最后一个表达式, 逗号运算符的优先级比赋值还低
语法
表达式1,表达式2
复制代码