JS运算符完全攻略 图片看不了?点击切换HTTP 返回上层
JavaScript 定义了 47个运算符,另有 4 个存在争议的运算符。它们具有多重功能,在不同环境中可能会执行不同的操作,而且它们拥有更高的优先级(15级)。简单说明如下:
不同的运算符需要配合的操作数的个数不同,可以分为以下 3 类:
JavaScript 能够根据运算环境自动转换操作数的类型,以便完成运算任务。
在下面代码中,两个操作数都是字符串,于是 JavaScript 自动把它们转换为数字,并执行减法运算,返回数字结果。
使用小括号可以改变运算符的优先顺序。例如,(1+2)*3 结果是 9,而不是7。
在下面代码中,第二行与第三行返回结果相同,但是它们的运算顺序是不同的。第二行先计算 5 减 2,最后赋值给变量 n,并显示变量 n 的值;而第三行先计算 5 减 2,再把结果赋值给变量 n,最后变量 n 乘以 2 ,并显示两者所乘结果。
在下面代码中,右侧的 typeof 运算符先与数字 5 结合,运算结果是字符串“number”,然后左侧的 typeof 运算符再与返回的字符串“number”结合,运算结果是字符串“string”。
对于下面表达式,左侧加号先结合,1+2 等于 3;然后 3 与右侧加号结合,3+3 等于 6;6 再与右侧加号结合,6+4 等于 10;最后返回结果。
运算符一般不会对操作数本身产生影响。例如,a=b+c,其中的操作数 b 和 c 不会因为加法运算而导致自身的值发生变化。不过,具有赋值功能的运算符能够改变操作数的值,进而潜在干扰程序的运行状态,并可能对后面的运算造成影响,因此具有一定的副作用,使用时应该保持警惕。具体说明如下:
从可读性考虑,在一个表达式中最好不要对同一个操作数执行两次或多次赋值运算。
- .(点号):读、写对象的属性,语法格式为“对象...属性”。
- [](中括号):读、写数组的元素,或者读、写对象的属性,语法格式为“数组[整数]”“对象['属性名称']”。
- ()(小括号):定义函数、调用函数、表达式分组等,常用语法格式为“函数(参数)”“(表达式)”。
- new:创建实例对象或者调用函数,语法格式为“new类型”“new函数”。
操作数的个数
一般情况下,运算符与操作数配合才能使用。其中,运算符指定执行运算的方式,操作数提供运算的内容。例如,1 加 1 等于 2,用表达式表示就是“n=1+1”。其中,1 是被操作的数,符号+
表示两个值相加的运算,符号=
表示赋值运算,n 表示接受赋值的变量。不同的运算符需要配合的操作数的个数不同,可以分为以下 3 类:
- 一元运算符:一个操作符仅对一个操作数执行某种运算,如取反、递加、递减、转换数字、类型检测、删除属性等运算。
- 二元运算符:一个运算符必须包含两个操作数。例如,两个数相加、两个值比较大。大部分运算符都需要操作数配合才能够完成运算。
-
三元运算符:一个运算符必须包含三个操作数。JavaScript 中仅有一个三元运算符——条件运算符
?:
(if语句的简化形式)。
操作数的类型
运算符操作的数据并不是随意的,大部分都有类型限制。例如加、减、乘、除四则运算要求参与的操作数必须是数值,逻辑运算要求参与的操作数必须是布尔值。另外,每个运算符执行运算之后,都会有明确的返回类型。JavaScript 能够根据运算环境自动转换操作数的类型,以便完成运算任务。
在下面代码中,两个操作数都是字符串,于是 JavaScript 自动把它们转换为数字,并执行减法运算,返回数字结果。
console.log("10"-"20"); //返回-10在下面代码中,数字 0 本是数值类型,JavaScript 会把它转换为布尔值 false,然后再执行条件运算。
console.log(0 ? 1 : 2); //返回2在下面代码中,字符串 5 被转换为数字,然后参与大小比较运算,并返回布尔值。
console.log(3 > "5"); //返回false在下面代码中,数字 5 被转换为字符编码,参与字符串的顺序比较运算。
console.log("a" > 5); //返回false在下面代码中,加号运算符能够根据数据类型执行相加或者相连运算。
console.log(10 + 20); //返回30 console.log("10" + "20"); //返回"1020"在下面代码中,布尔值 true 被转换为数字 1,参与乘法运算,并返回 5。
console.log(true * "5"); //返回5
运算符的优先级
运算符的优先级决定执行运算的顺序。例如,1+2*3 结果是 7。而不是 9,因为乘法优先级高,虽然加号位于左侧。使用小括号可以改变运算符的优先顺序。例如,(1+2)*3 结果是 9,而不是7。
在下面代码中,第二行与第三行返回结果相同,但是它们的运算顺序是不同的。第二行先计算 5 减 2,最后赋值给变量 n,并显示变量 n 的值;而第三行先计算 5 减 2,再把结果赋值给变量 n,最后变量 n 乘以 2 ,并显示两者所乘结果。
console.log(n=5-2*2); //返回1 console.log(n=(5-2)*2); //返回6 console.log((n=5-2)*2); //返回6
注意:
不正确的使用小括号也会引发异常。console.log((1+n=5-2)*2); //返回异常在上面代码中,加号运算符优先级高,先执行加运算,但是此时的变量 n 还是一个未知数,所以就会抛出异常。
运算符的结合性
一元运算符、三元运算符和赋值运算符都是按照先右后左的顺序进行结合并运算。在下面代码中,右侧的 typeof 运算符先与数字 5 结合,运算结果是字符串“number”,然后左侧的 typeof 运算符再与返回的字符串“number”结合,运算结果是字符串“string”。
console.log(typeof typeof 5); //返回“string”其运算数序使用小括号表示如下:
console.log(typeof (typeof 5)); //返回“string”
对于下面表达式,左侧加号先结合,1+2 等于 3;然后 3 与右侧加号结合,3+3 等于 6;6 再与右侧加号结合,6+4 等于 10;最后返回结果。
1+2+3+4其运算顺序使用小括号表示如下:
((1+2)+3)+4
左值、赋值及其副作用
左值就是只能出现在赋值运算符左侧的值,在 JavaScript 中主要指变量、对象的属性、数组的元素。运算符一般不会对操作数本身产生影响。例如,a=b+c,其中的操作数 b 和 c 不会因为加法运算而导致自身的值发生变化。不过,具有赋值功能的运算符能够改变操作数的值,进而潜在干扰程序的运行状态,并可能对后面的运算造成影响,因此具有一定的副作用,使用时应该保持警惕。具体说明如下:
-
赋值运算符
=
-
附加操作的赋值运算符如
+=
、%=
等 -
递增
++
或递减--
运算符 - delete运算符(功能等同于赋值 undefined)
示例1
在下面代码中,变量 a 经过赋值运算和递加运算后,其值发生了两次变化。var a = 0; a++; console.log(a); //返回1
示例2
在下面代码中,变量 a 在参与运算的过程中,其值不断的被改写,显然这个程序干扰了程序的正常运行结果。var a = 1; a = (a++) + (++a) - (a++) - (++a); //返回-4拆解 (a++) + (++a) - (a++) - (++a) 表达式如下:
var a = 1; b = a++; c = ++a; d = a++; e = ++a; console.log(b+c-d-e);
从可读性考虑,在一个表达式中最好不要对同一个操作数执行两次或多次赋值运算。
示例3
下面代码由于每个操作数仅执行了一次赋值运算,所以不会引发歧义,也不会干扰后续运算。a = (b++) + (++c) - (d++) - (++e); console.log(a); //返回-4