在前端开发过程中,JS 作为一种常用的脚本语言,承载着丰富的运算和操作功能。这些功能主要通过各种运算符来实现。本文将全面介绍 JS 中的各种运算符,并通过实例来加深理解。
本文将带你走进前端运算符的世界,从基础到高级,从常见到罕见,逐一解析它们的用法、特性和注意事项。我们将探讨算术运算符、比较运算符、逻辑运算符、位运算符、赋值运算符等各类运算符的工作原理,并通过实例展示如何在实际开发中运用它们。
掌握好各种运算符有利于代码的可读性
我们这边先来写几个实战,提高下兴趣,光看不会用也白搭。
实战
1.将一个值强制转换为布尔值
假如我们需要判断a是否存在,通常做法应该是 if(a){}
, 这时我们对a的类型不确定,我们需要的做法是:
const a = null // 可能为 '' 可能为undefined
let flag = true
if(!!a) {
// do someing
flag = !!a
}
连续使用两个 !
运算符 !!
的目的通常是将一个值强制转换为布尔值。这是因为 !
运算符会将其操作数转换为一个布尔值,然后再次取反。通过这种方式,任何非布尔值都可以被转换为一个明确的 true
或 false
。
!!
在开发中常被用作一种快捷的方式来进行显式的布尔类型转换。
2.将数字转换为整数
更常见和更明确的方法是使用 Math.floor()
, Math.ceil()
, Math.round()
, 或简单的类型转换(如 Number(value)
或 value | 0
)来得到整数。
console.log(~~4.9); // 输出: 4
console.log(~~-4.9); // 输出: -4
~~
的行为类似于将数字转换为整数。它首先对其操作数执行按位非操作(~
),然后再执行一次按位非操作。由于按位非操作是对数字的二进制表示进行操作的,因此这种双重操作最终会去掉数字的小数部分,从而得到一个整数。
它可以被用作一种技巧来将数字转换为整数。
3.优化存储空间
假设你正在处理大量的布尔值数据,并且想要有效地存储这些数据。由于布尔值只有两种状态(真或假),你可以使用单个位来存储每个布尔值,而不是使用完整的字节或更大的数据类型。
function storeBooleans(bools) {
let bits = 0;
let position = 0;
for (let i = 0; i < bools.length; i++) {
if (bools[i]) {
bits |= (1 << position); // 设置对应位为1
}
position++;
if (position >= 32) { // 32位是一个整数的最大位数
// 处理当前的整数,并重置位置和bits
// ...
position = 0;
bits = 0;
}
}
// 返回存储布尔值的整数数组或其他数据结构
return [bits]; // 这里只返回了一个整数作为示例
}
const booleans = [true, false, true, true, false];
const stored = storeBooleans(booleans);
console.log(stored); // 输出存储布尔值的整数数组
4.实现简单的哈希函数
位运算可以用于创建简单的哈希函数,该函数可以将一个字符串或数字映射到一个较小的整数范围。
function simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i); // 左移、减去自身并加上字符的ASCII码
hash |= 0; // 确保hash是一个32位整数
}
return hash;
}
const str = "hello";
const hashed = simpleHash(str);
console.log(hashed); // 输出哈希值
5.图像处理中的颜色操作
在处理图像数据时,位运算可以用来快速地修改像素的颜色值。
function invertColor(color) {
// 假设color是一个由RGB组成的整数,其中红色、绿色和蓝色分别占据8位
const inverted = ~color & 0xFFFFFF; // 取反并保留低24位(RGB值)
return inverted;
}
const originalColor = 0xFF0000; // 红色
const invertedColor = invertColor(originalColor);
console.log(invertedColor.toString(16)); // 输出反转后的颜色值
6.检测一个数是否为2的幂
使用位运算可以高效地检测一个数是否是2的幂。
function isPowerOfTwo(n) {
return (n > 0) && ((n & (n - 1)) === 0);
}
console.log(isPowerOfTwo(4)); // 输出: true
console.log(isPowerOfTwo(6)); // 输出: false
7.交换两个变量的值
不使用临时变量,只使用位运算交换两个变量的值。
let a = 5;
let b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(a); // 输出: 10
console.log(b); // 输出: 5
8.切换位状态
假设你有一个整数,并且你想要切换(取反)它的某一位。你可以使用按位异或(^
)运算符来实现这一点。
let num = 5; // 二进制: 0101
let bitToFlip = 2; // 我们想要切换第2位(从右边数起,从0开始)
let mask = 1 << bitToFlip; // 创建一个掩码,第2位为1,其余为0
num = num ^ mask; // 切换num的第2位
console.log(num); // 输出: 7 (二进制: 0111)
9.检查某一位是否为1
你可以通过与运算(&
)和一个掩码来检查一个整数的某一位是否为1。
let num = 10; // 二进制: 1010
let bitToCheck = 1; // 我们想要检查第1位(从右边数起,从0开始)
let mask = 1 << bitToCheck; // 创建一个掩码,第1位为1,其余为0
let isBitSet = (num & mask) !== 0; // 如果结果为非0,则该位被设置
console.log(isBitSet); // 输出: true
10.设置某一位为1
你可以使用或运算(|
)来确保一个整数的某一位被设置为1。
let num = 3; // 二进制: 0011
let bitToSet = 2; // 我们想要设置第2位(从右边数起,从0开始)为1
let mask = 1 << bitToSet; // 创建一个掩码,第2位为1,其余为0
num = num | mask; // 设置num的第2位为1
console.log(num); // 输出: 7 (二进制: 0111)
11. 清除某一位
你可以使用按位与(&
)和取反(~
)运算符来清除一个整数的某一位。
let num = 7; // 二进制: 0111
let bitToClear = 1; // 我们想要清除第1位(从右边数起,从0开始)
let mask = ~(1 << bitToClear); // 创建一个掩码,第1位为0,其余为1
num = num & mask; // 清除num的第1位
console.log(num); // 输出: 6 (二进制: 0110)
12.位运算实现整数乘法
位运算也可以用来实现整数的乘法,尽管这在现代JavaScript引擎中可能不如内置的乘法运算符高效,但在某些特定场景下可能有用。
function multiply(a, b) {
let result = 0;
while (b > 0) {
if (b & 1) { // 检查b的最低位是否为1
result = result + a; // 如果是,则将a加到结果中
}
a <<= 1; // 将a左移一位(相当于乘以2)
b >>= 1; // 将b右移一位
}
return result;
}
console.log(multiply(5, 3)); // 输出: 15
这里基本以比较生僻的位运算为例子,基本运算比如三元、加减乘除等运算符,想必大家用的也不比我少
然而在实际开发中,位运算符的复杂运算通常用于性能优化、低级编码、图形处理、加密算法等场景。
运算符概念例子大全
算术运算符
算术运算符主要用于执行数值的加、减、乘、除等基本运算。
- 加法 (
+
):用于两个数值的相加,也可以用于字符串连接。 - 减法 (
-
):用于两个数值的相减。 - 乘法 (
*
):用于两个数值的相乘。 - 除法 (
/
):用于两个数值的相除。 - 取模 (
%
):返回两数相除的余数。 - 递增 (
++
):将变量的值加1。 - 递减 (
--
):将变量的值减1。
let a = 5;
let b = 3;
let sum = a + b; // 加法:8
let difference = a - b; // 减法:2
let product = a * b; // 乘法:15
let quotient = a / b; // 除法:1.6666666666666667
let remainder = a % b; // 取模:2
a++; // 执行后加1
--b; // 执行前先减1
比较运算符
比较运算符用于比较两个值的大小或是否相等。
- 等于 (
==
):检查两个值是否相等,会进行类型转换。 - 严格等于 (
===
):检查两个值是否严格相等,不会进行类型转换。 - 不等于 (
!=
):检查两个值是否不相等,会进行类型转换。 - 严格不等于 (
!==
):检查两个值是否严格不相等,不会进行类型转换。 - 大于 (
>
):检查左边的值是否大于右边的值。 - 小于 (
<
):检查左边的值是否小于右边的值。 - 大于等于 (
>=
):检查左边的值是否大于或等于右边的值。 - 小于等于 (
<=
):检查左边的值是否小于或等于右边的值。
let x = 10;
let y = 20;
let isEqual = x == y; // 相等:false
let isNotEqual = x != y; // 不相等:true
let isStrictEqual = x === y; // 严格相等:false
let isStrictNotEqual = x !== y; // 严格不相等:true
let isGreaterThan = x > y; // 大于:false
let isLessThan = x < y; // 小于:true
let isEqualLessThan = x <= y; // 小于等于 true
let isEqualGreaterThan= x >= y; // 大于等于:true
逻辑运算符
逻辑运算符用于组合或否定布尔值。
- 逻辑与 (
&&
):当两个操作数都为真时返回真。 - 逻辑或 (
||
):当两个操作数中至少有一个为真时返回真。 - 逻辑非 (
!
):返回操作数的反值。
let isTrue = true;
let isFalse = false;
let andResult = isTrue && isFalse; // 逻辑与:false
let orResult = isTrue || isFalse; // 逻辑或:true
let notResult = !isTrue; // 逻辑非:false
赋值运算符
赋值运算符用于给变量赋值。
- 赋值 (
=
):将右侧的值赋给左侧的变量。 - 加法赋值 (
+=
):将右侧的值加到左侧的变量上,并将结果赋值给左侧的变量。 - 减法赋值 (
-=
):从左侧的变量中减去右侧的值,并将结果赋值给左侧的变量。 - 乘法赋值 (
*=
):将左侧的变量乘以右侧的值,并将结果赋值给左侧的变量。 - 除法赋值 (
/=
):将左侧的变量除以右侧的值,并将结果赋值给左侧的变量。
let num = 5;
num += 3; // 相当于 num = num + 3; 结果:num 为 8
num -= 2; // 相当于 num = num - 2; 结果:num 为 6
num *= 4; // 相当于 num = num * 4; 结果:num 为 24
num /= 2; // 相当于 num = num / 2; 结果:num 为 12
三元运算符
条件运算符是一个特殊的运算符,它接受三个操作数,并根据条件返回两个值之一。
let age = 15;
let beverage = (age >= 21) ? "Beer" : "Juice"; // 根据年龄返回不同的饮料
console.log(beverage); // 输出 "Juice"
类型运算符
类型运算符用于确定变量的类型。
let str = "Hello";
let num = 42;
let strType = typeof str; // 字符串类型:"string"
let numType = typeof num; // 数字类型:"number"
位运算符
位运算符直接对二进制位进行操作,通常在处理低级编程或优化性能时使用。
- 按位与(
&
):对两个数的每一位执行与操作。只有当两个相应的二进制位都为1时,结果的该位才为1。 - 按位或(
|
):对两个数的每一位执行或操作。只要两个相应的二进制位中有一个为1,结果的该位就为1。 - 按位异或(
^
):对两个数的每一位执行异或操作。当两个相应的二进制位不同时,结果的该位为1;相同时,结果的该位为0。 - 按位非(
~
):对一个数的每一位执行非操作。二进制位的0变为1,1变为0。 - 左移(
<<
):将一个数的所有位向左移动指定的位数,右侧用0填充。 - 右移(
>>
):将一个数的所有位向右移动指定的位数,左侧用该数的符号位填充(正数用0填充,负数用1填充)。 - 无符号右移(
>>>
):将一个数的所有位向右移动指定的位数,左侧总是用0填充。这常用于处理无符号整数。
let a = 60; // 60 = 0011 1100
let b = 13; // 13 = 0000 1101
let andResult = a & b; // 12 = 0000 1100
let orResult = a | b; // 61 = 0011 1101
let xorResult = a ^ b; // 49 = 0011 0001
let notResult = ~a; // -61 = 1100 0011 (二进制补码形式)
let leftShift = a << 2; // 240 = 1111 0000
let rightShift a >> 2; // 15 = 0000 1111
let unsignedResult = b >>> 1; // 6 = 1101 0110
其他运算符
JS 还包含一些其他运算符,如 in
运算符用于检查对象是否含有某个属性,instanceof
运算符用于检测构造函数的 prototype
属性是否出现在对象的原型链中,delete
运算符用于删除对象的属性等。
let obj = {
name: "Alice",
age: 30
};
console.log("name" in obj); // 输出 true
console.log(obj instanceof Object); // 输出 true
delete obj.age;
console.log(obj.age); // 输出 undefined
总结
在复杂运算中,这些运算符可以组合使用,以实现各种复杂的逻辑和功能。同时,由于位运算
直接对二进制位
进行操作,因此通常比普通的算术运算更快,更适合处理大量数据或需要高效运算的场景。
原文链接:https://juejin.cn/post/7353226130822742070 作者:大码猴