JavaScript运算符
JavaScript 提供了多种运算符,用于在代码中执行各种操作。以下是一些主要的 JavaScript 运算符分类及其示例:
1. 算术运算符
- 加(+):两个数相加
- 减(-):第一个数减去第二个数
- 乘(*):两个数相乘
- 除(/):第一个数除以第二个数
- 取模(%):返回两个数相除的余数
- 递增(++):将变量的值增加 1
- 递减(--):将变量的值减少 1
算数运算符在编程中用于执行基本的数学运算,如加法、减法、乘法、除法和取模等。在 JavaScript 中,这些运算符被广泛用于数值计算和表达式求值。下面将详细讲解 JavaScript 中的算数运算符。
1. 加法运算符(+
)
加法运算符用于将两个数相加,或者将一个数与一个字符串连接(当其中一个操作数是字符串时,JavaScript 会将另一个操作数转换为字符串并执行字符串连接)。
let sum = 5 + 3; // 结果为 8
let message = "Hello " + "World"; // 结果为 "Hello World"
let numberAsString = 5 + "3"; // 结果为 "53",因为 JavaScript 进行了字符串连接
2. 减法运算符(-
)
减法运算符用于从第一个数中减去第二个数。
示例:
let difference = 10 - 5; // 结果为 5
3. 乘法运算符(*
)
乘法运算符用于将两个数相乘。
示例
let product = 3 * 4; // 结果为 12
4. 除法运算符(/
)
除法运算符用于将第一个数除以第二个数。如果两个操作数都是整数,结果将是浮点数(除非两个数都可以被整除,此时结果将是整数)。
示例:
let quotient = 10 / 2; // 结果为 5
let quotientWithFraction = 10 / 3; // 结果为 3.3333333333333335(近似值)
5. 取模运算符(%
)
取模运算符(也称为求余运算符)用于返回两个数相除的余数。
示例:
let remainder = 10 % 3; // 结果为 1
6. 递增运算符(++
)
递增运算符用于将变量的值增加 1。它可以作为前缀(++variable
)或后缀(variable++
)出现。作为前缀时,它先递增变量然后返回新值;作为后缀时,它先返回原始值然后递增变量。
示例:
let counter = 5;
console.log(++counter); // 输出 6,然后 counter 的值为 6
counter = 5;
console.log(counter++); // 输出 5,然后 counter 的值为 6
7. 递减运算符(--
)
递减运算符用于将变量的值减少 1。它的前缀和后缀行为与递增运算符类似。
示例:
let counter = 5;
console.log(--counter); // 输出 4,然后 counter 的值为 4
counter = 5;
console.log(counter--); // 输出 5,然后 counter 的值为 4
注意事项:
- 当使用除法运算符时,如果除数为 0,JavaScript 会返回
Infinity
(正无穷大)或-Infinity
(负无穷大),或者如果操作数之一是非数字,它可能会返回NaN
(非数字)。- 递增和递减运算符不能用于非数字类型的变量(例如字符串或对象),除非它们隐式或显式地转换为数字。
- 当使用复合赋值运算符(如
+=
、-=
等)时,确保右侧的值不会导致算术运算无效(例如,除数不能为零)。- 不同类型的值在进行算数运算时可能会进行类型转换,这称为“隐式类型转换”或“类型强制”。了解这些转换规则对于编写正确的代码很重要。
2. 赋值运算符
- 等于(=):将右侧的值赋给左侧的变量
- 加等于(+=):将右侧的值加到左侧的变量上,然后将结果赋值给左侧的变量
- 减等于(-=):从左侧的变量中减去右侧的值,然后将结果赋值给左侧的变量
- 乘等于(*=):将左侧的变量乘以右侧的值,然后将结果赋值给左侧的变量
- 除等于(/=):将左侧的变量除以右侧的值,然后将结果赋值给左侧的变量
- 取模等于(%=):将左侧的变量对右侧的值取模,然后将结果赋值给左侧的变量
赋值运算符在编程中扮演着非常重要的角色,因为它们用于将值或表达式的结果存储(或“赋值”)到变量中。在 JavaScript 中,最基本的赋值运算符是等号(=
),但还有其他几种复合赋值运算符,它们结合了赋值和算术操作。
1. 基本赋值运算符(=
)
基本赋值运算符是最简单和最常用的赋值运算符。它将右侧的值(称为“右值”或“表达式”)赋给左侧的变量(称为“左值”或“变量”)。
示例:
let x = 10; // 将数字 10 赋值给变量 x
let y = x; // 将变量 x 的值(10)赋值给变量 y
2. 复合赋值运算符
复合赋值运算符结合了算术运算符和赋值运算符,允许你在赋值的同时对变量进行算术操作。这些运算符使得代码更加简洁。
2.1 加等于(+=
)
将右值加到左值上,然后将结果赋给左值。
示例:
let a = 5;
a += 3; // 相当于 a = a + 3; 现在 a 的值是 8
2.2 减等于(-=
)
从左值中减去右值,然后将结果赋给左值。
示例:
let b = 10;
b -= 4; // 相当于 b = b - 4; 现在 b 的值是 6
2.3 乘等于(*=
)
将左值乘以右值,然后将结果赋给左值。
示例:
let c = 2;
c *= 3; // 相当于 c = c * 3; 现在 c 的值是 6
2.4 除等于(/=
)
将左值除以右值,然后将结果赋给左值。
示例:
let d = 12;
d /= 4; // 相当于 d = d / 4; 现在 d 的值是 3
2.5 取模等于(%=
)
将左值对右值取模,然后将结果赋给左值。
示例:
let e = 10;
e %= 3; // 相当于 e = e % 3; 现在 e 的值是 1
注意事项
- 赋值运算符的左侧必须是一个可以赋值的表达式,通常是变量、数组元素、对象属性等。
- 赋值运算符的右侧可以是任何类型的值或表达式。
- 赋值操作会返回被赋的值,因此可以在表达式中链式使用赋值运算符。例如:
let a = b = c = 5;
这行代码将 5 赋值给 c,然后将 c 的值(5)赋值给 b,最后将 b 的值(5)赋值给 a。- 在使用复合赋值运算符时,要确保右侧的值不会导致算术运算无效(例如,除数不能为零)。
3. 比较运算符
- 等于(==):比较两个值是否相等(类型会进行转换)
- 不等于(!=):比较两个值是否不相等(类型会进行转换)
- 全等(===):比较两个值是否相等,并且它们的类型也必须相同
- 不全等(!==):比较两个值是否不相等,或者它们的类型不同
- 大于(>):比较左侧的值是否大于右侧的值
- 小于(<):比较左侧的值是否小于右侧的值
- 大于等于(>=):比较左侧的值是否大于或等于右侧的值
- 小于等于(<=):比较左侧的值是否小于或等于右侧的值
在JavaScript中,比较运算符用于比较两个值的大小、相等性或某种关系。以下是使用JavaScript比较运算符时需要注意的事项:
区分比较运算符和赋值运算符:
比较运算符(如
==
,===
,!=
,!==
,<
,>
,<=
,>=
)用于比较两个值。而赋值运算符(=
)用于给变量赋值。不要混淆这两者。了解严格相等(
===
)和非严格相等(==
)的区别:
- 严格相等(
===
)会同时比较值和类型。如果两个操作数的值和类型都相同,则结果为true
。- 非严格相等(
==
)在比较之前会进行类型转换,尝试使两个操作数的类型相同。这可能导致一些意外的结果,因此通常推荐使用严格相等。注意
null
和undefined
的比较:
null == undefined
会返回true
,因为它们都表示“无”或“空”的概念,但在严格相等(===
)中,null !== undefined
。- 如果你想检查一个变量是否为
null
或undefined
,可以使用x == null
(但要注意,这也会匹配到空字符串、0、NaN等“假值”类型的值,如果你只想检查null
和undefined
,应该使用x === null || x === undefined
)。注意NaN的比较:
- NaN(Not-a-Number)是一个特殊的值,表示非数字结果。在JavaScript中,
NaN === NaN
会返回false
,因为NaN不等于任何值,包括它自己。要检查一个值是否为NaN,可以使用isNaN()
函数。了解比较运算符的优先级:
- 比较运算符的优先级通常低于算术运算符和逻辑运算符。如果需要改变运算的优先级,可以使用括号。
避免隐式类型转换:
- 在使用非严格相等(
==
)时,JavaScript会尝试进行隐式类型转换以使两个操作数类型相同。这可能会导致意外的结果,因此通常推荐使用严格相等(===
)。注意浮点数的比较:
- 由于计算机内部表示浮点数的精度限制,直接比较两个浮点数是否相等可能会因为微小的舍入误差而失败。如果需要比较浮点数是否“接近相等”,可以定义一个小的容差值(epsilon),并检查两个数的差的绝对值是否小于这个容差值。
注意字符串的比较:
- 字符串的比较是基于字符的Unicode码点值。例如,'b' 在 'a' 之后,因为 'b' 的Unicode码点值大于 'a'。
注意对象比较:
- 在JavaScript中,对象(包括数组和函数)的比较是基于引用的,而不是基于内容的。即使两个对象的内容完全相同,如果它们是不同的引用,比较结果也会是
false
。要比较两个对象的内容是否相同,需要编写自定义的比较函数或使用专门的库。可读性和清晰性:
- 当使用复杂的比较表达式时,确保代码的可读性和清晰性。使用括号、空格和有意义的变量名来提高代码的可读性。考虑将复杂的比较逻辑拆分成多个简单的语句或函数。
4. 逻辑运算符
- 逻辑与(&&):如果两个操作数都为真,则结果为真
- 逻辑或(||):如果两个操作数中至少有一个为真,则结果为真
- 逻辑非(!):对操作数的布尔值进行取反
在使用JavaScript的逻辑运算符时,有一些注意事项可以帮助你编写更清晰、更健壮的代码。以下是关于JavaScript逻辑运算符使用的一些建议和注意事项:
- 理解逻辑运算符的行为:
- 逻辑与(
&&
):如果两个操作数都为真,则结果为真。如果第一个操作数为假,则不会评估第二个操作数(短路求值)。- 逻辑或(
||
):如果两个操作数中至少有一个为真,则结果为真。如果第一个操作数为真,则不会评估第二个操作数(短路求值)。- 逻辑非(
!
):将操作数的真值取反。- 短路求值(Short-Circuit Evaluation):
- 如上所述,
&&
和||
运算符具有短路求值的特性。这意味着如果第一个操作数的值已经足够确定整个表达式的值,那么就不会评估第二个操作数。这可以用于条件赋值或其他需要基于某个条件执行代码的情况。- 类型强制:
- 在使用逻辑运算符时,JavaScript会进行类型强制。例如,当使用逻辑与或逻辑或运算符时,操作数会被转换为布尔值(true或false)。了解这些类型转换规则可以帮助你预测和解释代码的行为。
- 不要过度依赖短路求值:
- 虽然短路求值在某些情况下很有用,但过度依赖它可能会导致代码难以理解和维护。尽量保持代码的清晰和直观,避免使用过于复杂的逻辑表达式。
- 避免在逻辑表达式中使用赋值运算符:
- 由于赋值运算符(
=
)和逻辑与运算符(&&
)的符号相似,很容易混淆。确保不要在逻辑表达式中意外地使用赋值运算符。- 明确逻辑表达式的意图:
- 编写逻辑表达式时,确保它们清晰地表达了你的意图。避免使用过于复杂的逻辑表达式,而是将它们拆分成多个简单的语句或函数。
- 测试边界条件:
- 当使用逻辑运算符编写代码时,确保测试各种边界条件。这包括测试真值、假值、未定义值(
undefined
)、空值(null
)、空字符串(''
)、零(0
)和非数字值(NaN
)等。确保你的代码在各种情况下都能按预期工作。- 使用括号明确优先级:
- 逻辑运算符的优先级可能与你预期的不同。使用括号可以明确指定运算的优先级,使代码更易于理解。
- 避免在逻辑表达式中使用复杂的算术或函数调用:
- 逻辑表达式应该简洁明了,避免在其中包含复杂的算术或函数调用。如果逻辑表达式变得过于复杂,考虑将其拆分成多个简单的语句或函数。
- 使用代码格式化工具:
- 使用代码格式化工具(如Prettier、ESLint等)可以帮助你保持代码的一致性和可读性。这些工具可以自动调整你的代码格式,包括逻辑表达式的缩进和空格等。
5. 位运算符
位运算符在 JavaScript 中不常用,但它们在处理位级操作时非常有用。例如:
- 位与(&)
- 位或(|)
- 位异或(^)
- 位非(~)
- 左移(<<)
- 右移(>>)
- 无符号右移(>>>)
JavaScript的位运算符主要用于对二进制位进行操作。这些运算符在处理整数(在JavaScript中,位运算符仅对32位整数有效)时可以提供高效的位级操作。下面详细讲解JavaScript中的位运算符:
1.位非(Bitwise NOT)~
位非运算符是一元运算符,它将操作数的每一位都取反(0变为1,1变为0)。然后,对结果执行减1操作(即取补码)。这是因为JavaScript中的位运算符处理的是有符号整数(通常是补码形式)。
示例:
let num = 5; // 二进制表示: 0101
let result = ~num; // 二进制表示: 1010(取反)再减1,得到结果(具体取决于JavaScript内部如何表示负数)
console.log(result); // 输出一个负数,具体值取决于系统
2.位与(Bitwise AND)&
位与运算符比较两个位,只有当两个相应的二进制位都为1时,结果位才为1。
示例:
let a = 5; // 二进制表示: 0101
let b = 3; // 二进制表示: 0011
let result = a & b; // 二进制表示: 0001(即十进制的1)
console.log(result); // 输出 1
3.位或(Bitwise OR)|
位或运算符比较两个位,只要两个相应的二进制位中有一个为1,结果位就为1。
示例:
let a = 5; // 二进制表示: 0101
let b = 3; // 二进制表示: 0011
let result = a | b; // 二进制表示: 0111(即十进制的7)
console.log(result); // 输出 7
4.位异或(Bitwise XOR)^
位异或运算符比较两个位,如果两个相应的二进制位不同,则结果位为1;如果相同,则结果位为0。
示例:
let a = 5; // 二进制表示: 0101
let b = 3; // 二进制表示: 0011
let result = a ^ b; // 二进制表示: 0110(即十进制的6)
console.log(result); // 输出 6
5.左移(Left Shift)<<
左移运算符将二进制表示的所有位向左移动指定的位数,右侧用0填充。这相当于将数字乘以2的指定次幂。
示例:
let num = 4; // 二进制表示: 0100
let result = num << 1; // 二进制表示: 1000(即十进制的8)
console.log(result); // 输出 8
6.有符号右移(Signed Right Shift)>>
有符号右移运算符将二进制表示的所有位向右移动指定的位数,左侧用符号位填充(正数用0填充,负数用1填充)。这相当于将数字除以2的指定次幂并向下取整。
示例:
let num = 8; // 二进制表示: 1000
let result = num >> 1; // 二进制表示: 0100(即十进制的4)
console.log(result); // 输出 4
7.无符号右移(Unsigned Right Shift)>>>
无符号右移运算符与有符号右移运算符类似,但它总是用0填充左侧,不考虑原数的符号。这在处理无符号整数或需要保持正数时很有用。
示例:
let num = -8; // 二进制表示(补码): 1111 1000
let result = num >>> 1; // 二进制表示: 0111 1100(即十进制的124)
console.log(result); // 输出 124
注意:由于JavaScript中的位运算符处理的是32位整数,因此当你使用大于32位的数字时,结果可能会与预期不符。
6. 字符串运算符
在 JavaScript 中,加号(+)也被用作字符串连接符,用于连接两个或多个字符串。
在JavaScript中,字符串运算符主要是+
,但它并不总是作为字符串运算符使用。然而,当+
运算符的任一操作数是字符串时,它通常会将其他操作数转换为字符串并进行字符串连接。
字符串连接
当使用+
运算符连接两个字符串时,它会将它们连接在一起。
let str1 = "Hello, ";
let str2 = "World!";
let result = str1 + str2; // "Hello, World!"
隐式类型转换
如果+
运算符的一个操作数是字符串,而另一个是数字、布尔值或其他类型的值,那么JavaScript会尝试将该值转换为字符串,然后进行连接。
let str = "The number is: " + 123; // "The number is: 123"
let boolStr = "The boolean is: " + true; // "The boolean is: true"
注意,当与null
或undefined
相加时,结果可能会有些出乎意料,因为null
转换为字符串是"null"
,而undefined
转换为字符串是"undefined"
。
let strWithNull = "Null value: " + null; // "Null value: null"
let strWithUndefined = "Undefined value: " + undefined; // "Undefined value: undefined"
7. 条件(三元)运算符
条件运算符也被称为三元运算符,因为它需要三个操作数。它的语法是:条件 ? 值1 : 值2
。如果条件为真,则运算符返回值1;如果条件为假,则运算符返回值2。
在JavaScript中,条件(三元)运算符也被称为三元条件运算符或条件表达式。这个运算符允许你根据某个条件的结果来返回两个值中的一个。它的语法如下:
condition ? value_if_true : value_if_false;
condition
是要被求值的条件。value_if_true
如果条件为真,则返回的值。value_if_false
如果条件为假,则返回的值。
let x = 10;
let y = (x > 5) ? "x is greater than 5" : "x is less than or equal to 5";
console.log(y); // 输出 "x is greater than 5"
在这个例子中,我们检查变量 x
是否大于5。如果是,我们返回字符串 "x is greater than 5"
;否则,我们返回 "x is less than or equal to 5"
。
条件运算符提供了一种在一行中执行条件判断并返回值的简洁方法,而不必使用if-else
语句。但是,如果逻辑变得更加复杂,那么使用if-else
语句可能更容易理解和维护。
8. 类型运算符
- typeof:返回一个表示变量类型的字符串
- instanceof:检测构造函数的
prototype
属性是否出现在对象的原型链中的任何位置
在JavaScript中,虽然没有直接称为“类型运算符”的特定运算符,但我们可以使用几种不同的方式来检查或确定一个值的类型。以下是一些常用的方法:
- typeof 运算符:
typeof
是一个一元运算符,它返回一个表示未经计算的操作数类型的字符串。
let num = 123;
console.log(typeof num); // "number" let str = "hello";
console.log(typeof str); // "string" let bool = true;
console.log(typeof bool); // "boolean" let obj = {};
console.log(typeof obj); // "object" let arr = [];
console.log(typeof arr); // 注意:这里返回 "object",但数组实际上是对象的一种特殊形式 let nullVar = null;
console.log(typeof nullVar); // "object"(历史遗留问题,实际上应该返回 "null") let undefVar;
console.log(typeof undefVar); // "undefined" let symbolVar = Symbol('mySymbol');
console.log(typeof symbolVar); // "symbol" (ES6 引入) let func = function() {};
console.log(typeof func); // "function"
- instanceof 运算符:
instanceof
运算符用于检测构造函数的prototype
属性是否出现在对象的原型链中的任何位置。这通常用于确定一个对象是否是一个类的实例。let arr = []; console.log(arr instanceof Array); // true let date = new Date(); console.log(date instanceof Date); // true let obj = {}; console.log(obj instanceof Object); // true
- Object.prototype.toString.call() 方法:
这个方法经常被用来获取一个对象的准确类型,因为它可以绕过typeof
的一些限制(比如typeof null
返回"object"
)。let arr = []; console.log(Object.prototype.toString.call(arr)); // "[object Array]" let date = new Date(); console.log(Object.prototype.toString.call(date)); // "[object Date]" let nullVar = null; console.log(Object.prototype.toString.call(nullVar)); // "[object Null]" let undefVar; console.log(Object.prototype.toString.call(undefVar)); // "[object Undefined]"
注意:虽然
Object.prototype.toString.call()
可以提供更准确的结果,但在大多数情况下,typeof
和instanceof
就足够了。使用Object.prototype.toString.call()
通常是在需要更精确的类型检测时才使用的。
- constructor 属性:
每个对象都有一个constructor
属性,它引用创建该对象的构造函数。但是,这种方法并不总是可靠的,因为constructor
属性可以被更改。let arr = []; console.log(arr.constructor === Array); // true let date = new Date(); console.log(date.constructor === Date); // true
- Array.isArray() 方法(特定于数组):
这个方法专门用来检测一个值是否为数组。let arr = []; console.log(Array.isArray(arr)); // true let obj = {}; console.log(Array.isArray(obj)); // false
9. 指数运算符
- ****():从 ES2016 开始,JavaScript 引入了新的指数运算符
**
,用于计算数的幂。例如,2 ** 3
等于 8。
在JavaScript中,指数运算符(也称为幂运算符)是**
。这个运算符允许你计算一个数的任意次幂。
以下是使用指数运算符的一些示例:
let base = 2;
let exponent = 3;
let result = base ** exponent; // 计算 2 的 3 次方
console.log(result); // 输出 8 let square = 4 ** 0.5; // 计算 4 的平方根
console.log(square); // 输出 2 let cubeRoot = 27 ** (1/3); // 计算 27 的立方根
console.log(cubeRoot); // 输出 3 let negativeExponent = 2 ** -3; // 计算 2 的 -3 次方,即 1 / (2^3)
console.log(negativeExponent); // 输出 0.125
指数运算符在ES2016(ECMAScript 2016)中引入,它提供了一种更简洁、更直观的方式来表示幂运算,而不需要使用Math.pow()
函数。
注意:在旧版本的JavaScript中,你可能需要使用Math.pow()
函数来计算幂运算,例如Math.pow(base, exponent)
。但在现代JavaScript环境中,你可以直接使用**
运算符。
10. 展开运算符(Spread Operator)和剩余运算符(Rest Operator)
- 展开运算符(...):用于函数参数展开或数组字面量展开。
- 剩余运算符(...):用于获取函数的多余参数(作为数组)或用于解构数组的剩余部分。
这些运算符提供了在 JavaScript 中执行各种操作的能力。