运算符是解决数据运算的问题
操作符和操作数
操作符: 运输符,参与运算的符号 操作数: 参与运算的数据,也称之为"元".
操作符不一定只有一个符合,操作符出现的问题不同,可能具有不同的含义。
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,得到的表达式的值是自减之后的值。
- 优先级运算的细节
1.从左往右依次查看
2.如果遇到操作数,将数据直接取出
3.如果遇到相邻的两个运算符,并且左边的运算符优先级大于右边的运算符,则直接运行左边的运算符,否则运算右边的运算符。
金典面试题
先来一道简单的
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)
- 如果其中数据是引用类型,需要将引用类型转成原始类型,然后来进行比较.
相等比较注意事项
== 比较两个数据是否相等,!= 比较两个数据不相等
- 左右两端的数据类型相同,直接比较两个数据本身是否相同(引用类型比较的是引用的地址)
- 两端数据不相同
1.null 和 undefined, 他们直接相等,和其他原始类型比较,不相等
2.NaN 与任何值比较,都是false, Infinity 只等于它自身
3.引用类型和原始类型比较, 引用类型需要转换成原始类型进行比较。
4.其他原始类型,比较时候会自动调用 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 复制代码