JavaScript 运算符是用于对作数(值和变量)执行作的符号。以下是 JavaScript 中的一些主要运算符类型:
-
算术运算符:用于对数字执行算术运算。
- 加法 (
+
) - 减法 (
-
) - 乘法 (
*
) - 除法 (
/
) - 模量 (
%
) - 增量 (
++
) - 递减 (
--
)
- 加法 (
-
赋值运算符:用于为变量赋值。
- 分配 (
=
) - 加法赋值 (
+=
) - 减法赋值 (
-=
) - 乘法赋值 (
*=
) - 除法分配 (
/=
) - 模数分配 (
%=
)
- 分配 (
-
比较运算符:用于比较两个值。
- 等于 (
==
) - Strict 等于 (
===
) - 不等于 (
!=
) - 严格不等于 (
!==
) - 大于 (
>
) - 小于 (
<
) - 大于或等于 (
>=
) - 小于或等于 (
<=
)
- 等于 (
-
逻辑运算符:用于执行逻辑作。
- 和 (
&&
) - 或 (
||
) - 非 (
!
)
- 和 (
-
Bitwise Operators:用于执行位级运算。
- 和 (
&
) - 或 (
|
) - 非 (
~
) - 异或 (
^
) - 左移 (
<<
) - 右移 (
>>
) - 零填充右移 (
>>>
)
- 和 (
-
字符串运算符:用于连接字符串。
- 串联 (
+
) - 串联赋值 (
+=
)
- 串联 (
-
条件 (三元) 运算符: 用于根据条件分配值。
- 三元 (
condition ? expr1 : expr2
)
- 三元 (
-
类型运算符:用于确定变量的类型。
typeof
instanceof
运算符优先级确定运算符在表达式中的计算顺序。在 JavaScript 中,优先级较高的运算符在优先级较低的运算符之前进行评估。以下是运算符优先级从最高到最低的摘要:
- 分组:
()
- Member Access: 和
.
[]
- 函数调用:
()
- 带参数的新增功能:
new
- 后缀递增/递减:和
++
--
- 逻辑 NOT:
!
- 按位 NOT:
~
- 一元加/减:和
+
-
- typeof, void, delete: , , (类型)
typeof
void
delete
- 幂:
**
- 乘法/除法/模数: , ,
*
/
%
- 加法/减法: ,
+
-
- 按位移位:、 、
<<
>>
>>>
- 关系: , , , ,
<
<=
>
>=
- 相等: , , ,
==
!=
===
!==
- 按位 AND:
&
- 按位 XOR
^
- 按位 OR:
|
- 逻辑 AND:
&&
- 逻辑 OR:
||
- 条件 (Ternary):
? :
- 分配: , , , ,
=
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
^=
|=
- 逗号:
,
例如,在表达式 中,首先执行乘法运算,因为 的优先级高于 ,导致 等于 。3 + 4 * 2
*
+
3 + 8
11
1. 算术运算符
JavaScript 算术运算符用于执行基本的数学运算。以下是主要的算术运算符:
- 加法 (+
):将两个数字相加。
let sum = 5 + 3; // sum is 8
- 减法 (
-
):从一个数字中减去另一个数字。
let difference = 10 - 4; // difference is 6
- 乘法 (
*
):将两个数字相乘。
let product = 7 * 6; // product is 42
- 除法 (
/
):将一个数字除以另一个数字。
let quotient = 20 / 4; // quotient is 5
- 模数 (
%
):返回除法的余数。
let remainder = 15 % 4; // remainder is 3
- 增量 (
++
):将数字增加 1。
let count = 5;
count++; // count is now 6
- 递减 (
--
):将数字减少 1。
let count = 5;
count--; // count is now 4
这些运算符可用于各种表达式来执行计算。例如:
let a = 10;
let b = 5;
let result = (a + b) * (a - b); // result is 75
在 JavaScript 中使用算术运算符有时会导致常见错误。以下是一些需要注意的事项:
- 运算符优先级不正确:忘记作顺序可能会导致意外结果。
let result = 5 + 3 * 2; // result is 11, not 16
// Correct way with parentheses:
let correctResult = (5 + 3) * 2; // correctResult is 16
- 类型强制转换:JavaScript 可以自动转换类型,这可能会导致意外结果。
let result = '5' + 3; // result is '53' (string), not 8
// Use parseInt or parseFloat to convert strings to numbers:
let correctResult = parseInt('5') + 3; // correctResult is 8
- 浮点精度:使用浮点数的运算可能会导致精度错误。
let result = 0.1 + 0.2; // result is 0.30000000000000004, not 0.3
// Use toFixed to limit the number of decimal places:
let correctResult = (0.1 + 0.2).toFixed(1); // correctResult is '0.3'
- 错误地使用
++
和--
:误解了前缀和后缀递增/递减之间的区别。
let count = 5;
let result = count++; // result is 5, count is 6
// Prefix version:
let correctResult = ++count; // correctResult is 7, count is 7
- 除以零:虽然 JavaScript 通过返回 来处理除以零,但它仍然可能导致逻辑错误。
Infinity
let result = 10 / 0; // result is Infinity
// Check for zero before dividing:
let divisor = 0;
let correctResult = divisor !== 0 ? 10 / divisor : 'Cannot divide by zero';
- 负数取模数:取数运算符的结果可能会与负数意外。
let result = -5 % 2; // result is -1, not 1
// Use Math.abs to get a positive result:
let correctResult = Math.abs(-5 % 2); // correctResult is 1
确定!JavaScript 中的类型强制是指值从一种数据类型到另一种数据类型的自动或隐式转换。这可能发生在各种上下文中,例如在使用运算符或比较值时。类型强制有两种类型:隐式和显式。
隐式类型强制
当 JavaScript 需要某种类型的值时,这会自动发生。以下是一些常见示例:
- 字符串强制转换:
let result = '5' + 3; // '53' (number 3 is coerced to a string)
- 号码强制:
let result = '5' - 3; // 2 (string '5' is coerced to a number)
- 布尔强制:
let result = !!'hello'; // true (non-empty string is coerced to true)
显式类型强制
当您使用函数或方法手动将值从一种类型转换为另一种类型时,会发生这种情况。以下是一些示例:
- 字符串到数字:
let num = Number('5'); // 5
let num = parseInt('5'); // 5
let num = parseFloat('5.5'); // 5.5
- Number to String(数字到字符串):
let str = String(5); // '5'
let str = (5).toString(); // '5'
- 布尔值到数字:
let num = Number(true); // 1
let num = Number(false); // 0
常见陷阱
类型强制有时会导致意外结果。以下是一些示例:
- 比较不同类型的产品:
let result = '5' == 5; // true (due to type coercion)
let result = '5' === 5; // false (strict equality, no type coercion)
- 假值:
let result = !!0; // false (0 is a falsy value)
let result = !!''; // false (empty string is a falsy value)
let result = !!null; // false (null is a falsy value)
- 意外的字符串连接:
let result = 5 + '5'; // '55' (number 5 is coerced to a string)
1. 赋值运算符
JavaScript 赋值运算符用于为变量赋值。
1. 分配 (=
)
用法:将右侧的值分配给左侧的变量。
- 示例:
let x = 10; // x is now 10
- 积极的一面:简单明了。
- 消极面:容易与相等运算符 () 混淆。
==
- 常见错误:
if (x = 5) { // This assigns 5 to x instead of comparing
console.log('x is 5');
}
// Correct way:
if (x == 5) { // This compares x to 5
console.log('x is 5');
}
2. 加法赋值 (+=
)
用法:将右侧的值添加到左侧的变量,并将结果分配给变量。
- 示例:
let x = 10;
x += 5; // x is now 15
- 正面:更新变量值的简洁方法。
- 消极面:如果不熟悉速记运算符,可能会令人困惑。
- 常见错误:
let x = '10';
x += 5; // x is now '105' (string concatenation)
// Correct way:
let x = parseInt('10');
x += 5; // x is now 15
3. 减法赋值 (-=
)
用法:从左侧的变量中减去右侧的值,并将结果分配给变量。
- 示例:
let x = 10;
x -= 3; // x is now 7
- 积极的一面:减少代码详细程度。
- 负面:如果初始值不是数字,则可能会被误用。
- 常见错误:
let x = '10';
x -= 3; // x is now 7 (string '10' is coerced to number 10)
// Correct way:
let x = parseInt('10');
x -= 3; // x is now 7
4. 乘法赋值 (*=
)
用法:将左侧的变量乘以右侧的值,并将结果分配给变量。
- 示例:
let x = 10;
x *= 2; // x is now 20
- 正面:高效更新值。
- 负值:可能会导致非数值的意外结果。
- 常见错误:
let x = '10';
x *= 2; // x is now 20 (string '10' is coerced to number 10)
// Correct way:
let x = parseInt('10');
x *= 2; // x is now 20
5. 部门分配 (/=
)
用法:将左侧的变量除以右侧的值,并将结果分配给变量。
- 示例:
let x = 10;
x /= 2; // x is now 5
- 积极的一面:简化除法作。
- 消极面:被零除可能会导致问题。
- 常见错误:
let x = 10;
x /= 0; // x is now Infinity
// Correct way:
let x = 10;
let y = 0;
let result = y !== 0 ? x / y : 'Cannot divide by zero'; // result is 'Cannot divide by zero'
6. 模数分配 (%=
)
用法:将左侧变量的模数除以右侧的值,并将结果分配给变量。
- 示例:
let x = 10;
x %= 3; // x is now 1
- 正极侧:适用于循环作。
- 负数:可能与负数混淆。
- 常见错误:
let x = -10;
x %= 3; // x is now -1
// Correct way:
let x = Math.abs(-10);
x %= 3; // x is now 1
总结
积极的一面:
- 简洁的语法:赋值运算符提供了一种更新变量的简写方法,使代码更加简洁和可读。
- 效率:它们可以通过减少常见作所需的行数来提高代码的效率。
缺点:
- 混淆:这些运算符可能会令人困惑,尤其是对于可能不熟悉速记表示法的初学者。
- 类型强制转换:JavaScript 的自动类型强制转换可能会导致意外结果,尤其是在处理字符串和数字时。
常见错误:
- 在条件中滥用赋值运算符:使用 instead of 或 in 条件可能会导致逻辑错误。
=
==
===
- 意外的类型强制转换:当使用不同数据类型的赋值运算符时,JavaScript 可能会以意外的方式强制类型。
- 除以零:除以零会导致 ,这可能会导致代码中出现逻辑错误。
Infinity
3.比较运算符
JavaScript 中的比较运算符用于比较两个值,并根据比较返回布尔值 ( 或 )。以下是主要的比较运算符:true
false
-
等于 (
==
):- 比较两个值是否相等,必要时执行类型强制转换。
- 例:
let result = (5 == '5'); // true (number 5 is coerced to string '5')
-
严格等于 (
===)
:- 比较两个值是否相等,而不执行类型强制转换。
- 例:
let result = (5 === '5'); // false (different types: number and string)
-
不等于 (
!=
):- 比较两个值的不等性,必要时执行类型强制转换。
- 例:
let result = (5 != '5'); // false (number 5 is coerced to string '5')
-
严格不等于 (
!==
):- 比较两个值的不等性,而不执行类型强制转换。
- 例:
let result = (5 !== '5'); // true (different types: number and string)
-
大于 (
>
):- 检查左侧的值是否大于右侧的值。
- 例:
let result = (10 > 5); // true
-
大于或等于 (
>=
):- 检查左侧的值是否大于或等于右侧的值。
- 例:
let result = (10 >= 10); // true
-
小于 (
<
):- 检查左侧的值是否小于右侧的值。
- 例:
let result = (5 < 10); // true
-
小于或等于 (
<=
):- 检查左侧的值是否小于或等于右侧的值。
- 例:
let result = (5 <= 5); // true
常见陷阱和最佳实践
-
键入带有
==
和!=
的 Coercion:- 陷阱:由于类型强制,使用 OR 可能会导致意外结果。
==
!=
- 最佳实践:使用 和 避免类型强制转换。
===
!==
- 例:
let result = (0 == false); // true (0 is coerced to false) let strictResult = (0 === false); // false (different types: number and boolean)
- 陷阱:由于类型强制,使用 OR 可能会导致意外结果。
-
比较不同类型的产品:
- 陷阱:比较不同类型的值可能会导致意外结果。
- 最佳实践:在比较之前,请确保值属于同一类型。
- 例:
let result = ('10' > 5); // true (string '10' is coerced to number 10) let correctResult = (parseInt('10') > 5); // true (both are numbers)
-
NaN 比较:
- Pitfall: (Not-a-Number) 不等于任何值,包括它自己。
NaN
- 最佳实践:用于检查 .
isNaN()
NaN
- 例:
let result = (NaN == NaN); // false let correctResult = isNaN(NaN); // true
- Pitfall: (Not-a-Number) 不等于任何值,包括它自己。
-
浮点精度:
- 陷阱:比较浮点数可能会导致精度错误。
- 最佳实践:使用容差值进行比较。
- 例:
let a = 0.1 + 0.2; let b = 0.3; let result = (a === b); // false (due to precision error) let correctResult = (Math.abs(a - b) < Number.EPSILON); // true
总结
- 积极的一面:比较运算符对于在代码中做出决策至关重要,例如在条件语句和循环中。
- 消极面:误解类型强制和精度问题可能会导致错误。
- 常见错误:使用 instead of 、 比较不同类型而不进行转换,以及使用浮点数的精度错误。
==
===
每种数据类型的比较
1. 数字
- 等于 (
==
):
let result = (5 == 5); // true
let result = (5 == '5'); // true (type coercion: string '5' is converted to number 5)
原因:运算符执行类型强制转换,在比较之前将字符串 '5' 转换为数字 5。==
- 严格等于 (
===)
:
let result = (5 === 5); // true
let result = (5 === '5'); // false (no type coercion: different types)
原因:运算符不执行类型强制转换,因此会同时比较 value 和 type。===
2. 字符串
- 等于 (
==
):
let result = ('hello' == 'hello'); // true
let result = ('hello' == 'Hello'); // false (case-sensitive comparison)
原因:字符串是逐个字符比较的,并且比较区分大小写。
- 严格等于 (
===)
:
let result = ('hello' === 'hello'); // true
let result = ('hello' === 'Hello'); // false (case-sensitive comparison)
原因:与 相同,但没有类型强制。==
3. 布尔值
- 等于 (
==
):
let result = (true == 1); // true (type coercion: true is converted to 1)
let result = (false == 0); // true (type coercion: false is converted to 0)
原因:运算符在比较之前将布尔值转换为数字。==
- 严格等于 (
===)
:
let result = (true === 1); // false (no type coercion: different types)
let result = (false === 0); // false (no type coercion: different types)
原因:运算符不执行类型强制转换,因此会同时比较 value 和 type。===
4. 对象
- 等于 (
==
):
let obj1 = { name: 'Alice' };
let obj2 = { name: 'Alice' };
let result = (obj1 == obj2); // false (different references)
let result = (obj1 == obj1); // true (same reference)
原因:对象按引用而不是按值进行比较。不同的对象具有不同的引用。
- 严格等于 (
===)
:
let obj1 = { name: 'Alice' };
let obj2 = { name: 'Alice' };
let result = (obj1 === obj2); // false (different references)
let result = (obj1 === obj1); // true (same reference)
原因:与 相同,但没有类型强制。==
5. 数组
- 等于 (
==
):
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
let result = (arr1 == arr2); // false (different references)
let result = (arr1 == arr1); // true (same reference)
原因:数组是对象,因此它们通过引用进行比较。
- 严格等于 (
===)
:
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
let result = (arr1 === arr2); // false (different references)
let result = (arr1 === arr1); // true (same reference)
原因:与 相同,但没有类型强制。==
6. 和null
undefined
- 等于 (
==
):
let result = (null == undefined); // true (both are considered equal)
let result = (null == null); // true
let result = (undefined == undefined); // true
原因:,并且在使用 .null
undefined
==
- 严格等于 (
===)
:
let result = (null === undefined); // false (different types)
let result = (null === null); // true
let result = (undefined === undefined); // true
原因:不执行类型强制转换,因此 和 不被视为相等。===
null
undefined
常见陷阱和最佳实践摘要
-
键入带有
==
和!=
的 Coercion:- 陷阱:由于类型强制,使用 OR 可能会导致意外结果。
==
!=
- 最佳实践:使用 和 避免类型强制转换。
===
!==
- 例:
let result = (0 == false); // true (0 is coerced to false) let strictResult = (0 === false); // false (different types: number and boolean)
- 陷阱:由于类型强制,使用 OR 可能会导致意外结果。
-
比较不同类型的产品:
- 陷阱:比较不同类型的值可能会导致意外结果。
- 最佳实践:在比较之前,请确保值属于同一类型。
- 例:
let result = ('10' > 5); // true (string '10' is coerced to number 10) let correctResult = (parseInt('10') > 5); // true (both are numbers)
-
NaN 比较:
- Pitfall: (Not-a-Number) 不等于任何值,包括它自己。
NaN
- 最佳实践:用于检查 .
isNaN()
NaN
- 例:
let result = (NaN == NaN); // false let correctResult = isNaN(NaN); // true
- Pitfall: (Not-a-Number) 不等于任何值,包括它自己。
-
浮点精度:
- 陷阱:比较浮点数可能会导致精度错误。
- 最佳实践:使用容差值进行比较。
- 例:
let a = 0.1 + 0.2; let b = 0.3; let result = (a === b); // false (due to precision error) let correctResult = (Math.abs(a - b) < Number.EPSILON); // true
4. 逻辑运算符
JavaScript 中的逻辑运算符用于对布尔值执行逻辑运算。它们对于在代码中做出决策至关重要,例如在条件语句和循环中。以下是主要的逻辑运算符:
1. 逻辑 AND (&&
)
- 用法:如果两个作数均为 ;否则,返回 .
true
true
false
- 示例:
let a = true;
let b = false;
let result = a && b; // false (because b is false)
let result2 = a && !b; // true (because !b is true)
- Short-Circuit Evaluation(短路计算):如果第一个作数为 ,则不计算第二个作数。
false
let result = false && (5 / 0); // false (5 / 0 is not evaluated)
2. 逻辑 OR (||
)
- 用法:如果至少有一个作数为 ;否则,返回 .
true
true
false
- 示例:
let a = true;
let b = false;
let result = a || b; // true (because a is true)
let result2 = !a || b; // false (because both !a and b are false)
- Short-Circuit Evaluation(短路计算):如果第一个作数为 ,则不计算第二个作数。
true
let result = true || (5 / 0); // true (5 / 0 is not evaluated)
3. 逻辑 NOT (!
)
- 用法:如果作数为 ;否则,返回 .
true
false
false
- 示例:
let a = true;
let result = !a; // false (because a is true)
let result2 = !false; // true
组合逻辑运算符
逻辑运算符可以组合成复杂的逻辑表达式:
let a = true;
let b = false;
let c = true;
let result = a && (b || c); // true (because b || c is true, and a is true)
常见陷阱和最佳实践
-
短路评估:
- 陷阱:依赖短路表达式中的副作用可能会导致意外行为。
- 最佳实践:避免逻辑表达式中的副作用。
- 例:
let x = 0; let result = (x !== 0) && (x = 1); // result is false, x is still 0
-
真值和假值:
- 陷阱:逻辑运算符处理真值和假值,而不仅仅是布尔值。
- 最佳实践: 注意哪些值被认为是真值或假值。
- 例:
let result = '' || 'default'; // 'default' (empty string is falsy) let result2 = 0 && 'value'; // 0 (0 is falsy)
-
双重否定 (
!!
):- 用法:将值转换为其布尔等效值。
- 例:
let result = !!'hello'; // true (non-empty string is truthy) let result2 = !!0; // false (0 is falsy)
总结
- 逻辑 AND (
&&
):如果两个作数都是 ,则返回 。true
true
- 逻辑 OR (
||
):如果至少有一个作数为 ,则返回 。true
true
- 逻辑 NOT (
!
):如果作数为 ,则返回 。true
false
在 JavaScript 中,真值和假值用于确定值的布尔上下文。当一个值在布尔上下文中被计算时(比如在语句或逻辑作中),它被认为是 “真 ”或 “假 ”。if
假值
假值是在布尔上下文中计算时考虑的值。JavaScript 中只有几个 falsy 值:false
错误
:
if (false) {
console.log('This will not be logged');
}
0
(零):
if (0) {
console.log('This will not be logged');
}
-0
(负零):
if (-0) {
console.log('This will not be logged');
}
0n
(BigInt 零):
if (0n) {
console.log('This will not be logged');
}
""
(空字符串):
if ("") {
console.log('This will not be logged');
}
null
:
if (null) {
console.log('This will not be logged');
}
undefined
的
if (undefined) {
console.log('This will not be logged');
}
NaN
(非数字):
if (NaN) {
console.log('This will not be logged');
}
Truthy 价值观
真值是所有不是假值的值。从本质上讲,任何不是上面列出的假值之一的值都被认为是真实的。以下是 truthy 值的一些示例:
- 非零数字:
if (42) {
console.log('This will be logged');
}
- 非空字符串:
if ("hello") {
console.log('This will be logged');
}
- 对象:
if ({}) {
console.log('This will be logged');
}
- 数组:
if ([]) {
console.log('This will be logged');
}
- 功能:
if (function() {}) {
console.log('This will be logged');
}
实例
使用 truthy 和 falsy 值可以简化代码中的条件检查。例如:
let name = ""; // falsy value
if (!name) {
console.log("Name is required"); // This will be logged
}
let count = 5; // truthy value
if (count) {
console.log("Count is valid"); // This will be logged
}
总结
- 假值: , , , ,
false
0
-0
0n
""
null
undefined
NaN
- 真值:所有非假值
5. 三元运算符
JavaScript 中的三元运算符是编写条件语句的简写方式。它也称为条件运算符。三元运算符采用三个作数,并且是 JavaScript 中唯一执行此作的运算符。语法为:
condition ? expr1 : expr2
- condition:计算结果为 或 的表达式。
true
false
- expr1:如果条件为 ,则执行的表达式。
true
- expr2:如果条件为 ,则执行的表达式。
false
例
下面是使用三元运算符的简单示例:
let age = 18;
let canVote = (age >= 18) ? 'Yes' : 'No';
console.log(canVote); // Output: 'Yes'
在此示例中,将评估条件。如果为 ,则该值将分配给 。如果为 ,则该值将分配给 。age >= 18
true
'Yes'
canVote
false
'No'
canVote
嵌套的三元运算符
你也可以嵌套三元运算符,但为了可读性,通常建议避免这样做:
let score = 85;
let grade = (score >= 90) ? 'A' :
(score >= 80) ? 'B' :
(score >= 70) ? 'C' :
(score >= 60) ? 'D' : 'F';
console.log(grade); // Output: 'B'
实际用例
- 根据条件赋值:
let isMember = true;
let discount = isMember ? 0.1 : 0;
console.log(discount); // Output: 0.1
- 内联条件渲染:
let isLoggedIn = false;
let message = isLoggedIn ? 'Welcome back!' : 'Please log in.';
console.log(message); // Output: 'Please log in.'
优势
- 简洁性:三元运算符允许您编写简洁的条件语句。
- 可读性:对于简单的情况,它可以使代码更具可读性。
弊
- 可读性:对于复杂条件或嵌套的三元运算符,它会使代码更难阅读和理解。
- 调试:与传统语句相比,调试可能更加困难。
if-else
总结
三元运算符是在 JavaScript 中编写简洁的条件语句的强大工具。但是,应谨慎使用它,以保持代码的可读性和调试的便利性。
使用三元运算符可能非常方便,但也有一些常见的陷阱需要注意。以下是一些:
1. 可读性问题
- 陷阱:过度使用三元运算符或嵌套它们会使代码难以阅读和理解。
- 示例:
let score = 85;
let grade = (score >= 90) ? 'A' :
(score >= 80) ? 'B' :
(score >= 70) ? 'C' :
(score >= 60) ? 'D' : 'F';
解决方案:对于复杂情况,请改用 statements。if-else
let grade;
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else if (score >= 60) {
grade = 'D';
} else {
grade = 'F';
}
2. 复杂逻辑中的误用
- 陷阱:对复杂逻辑使用三元运算符可能会导致错误并使调试变得困难。
- 示例:
let result = (a > b) ? (c > d) ? 'C';
解决方案:将复杂的逻辑分解为更简单、更具可读性的语句。
let result;
if (a > b) {
result = (c > d) ? 'A' : 'B';
} else {
result = 'C';
}
3. 副作用
- 陷阱:将三元运算符与具有副作用的表达式一起使用可能会导致意外行为。
- 示例:
let x = 0;
let result = (x > 0) ? (x = 1) : (x = 2); // x is now 2
.
let x = 0;
let result;
if (x > 0) {
x = 1;
result = x;
} else {
x = 2;
result = x;
}
4. 分配错误使用
- 陷阱:错误地使用三元运算符进行赋值可能会导致逻辑错误。
- 示例:
let isMember = true;
let discount = isMember ? 0.1 : 0.2; // Correct
isMember ? discount = 0.1 : discount = 0.2; // Incorrect, but works due to assignment precedence
解决方案:使用括号来阐明赋值。
isMember ? (discount = 0.1) : (discount = 0.2); // Correct
5. 过度使用
- 陷阱:过度使用三元运算符会使代码的可读性降低且更难维护。
- 示例:
let status = (age >= 18) ? 'adult' : (age >= 13) ? 'teen' : 'child';
解决方案:使用语句以提高可读性。if-else
let status;
if (age >= 18) {
status = 'adult';
} else if (age >= 13) {
status = 'teen';
} else {
status = 'child';
}
总结
虽然三元运算符可以使您的代码更简洁,但重要的是要明智地使用它们以保持可读性并避免逻辑错误。对于复杂情况或涉及副作用时,最好使用 statements。if-else
6. 按位运算符
JavaScript 中的按位运算符用于对数字的二进制表示执行作。这些运算符将其作数视为 32 位 (0 和 1) 的序列,并执行按位运算。以下是主要的按位运算符:
1. 按位 AND (&
)
- 用法:对作数的每对对应位执行按位 AND 运算。
- 示例:
let a = 5; // 0101 in binary
let b = 3; // 0011 in binary
let result = a & b; // 0001 in binary (1 in decimal)
2. 按位 OR (|
)
- 用法:对作数的每对对应位执行按位 OR 运算。
- 示例:
let a = 5; // 0101 in binary
let b = 3; // 0011 in binary
let result = a | b; // 0111 in binary (7 in decimal)
3. 按位 XOR (^
)
- 用法:对作数的每对对应位执行按位 XOR(异或)运算。
- 示例:
let a = 5; // 0101 in binary
let b = 3; // 0011 in binary
let result = a ^ b; // 0110 in binary (6 in decimal)
4. 按位 NOT (~
)
- 用法:反转作数的所有位(按位 NOT)。
- 示例:
let a = 5; // 0101 in binary
let result = ~a; // 1010 in binary (inverted, -6 in decimal due to two's complement representation)
5. 左移 (<<
)
- 用法:将作数的位向左移动指定的位置数,用零填充最右边的位。
- 示例:
let a = 5; // 0101 in binary
let result = a << 1; // 1010 in binary (10 in decimal)
6. 右移 (>>
)
- 用法:将作数的位向右移动指定数量的位置,保留符号位(符号传播)。
- 示例:
let a = 5; // 0101 in binary
let result = a >> 1; // 0010 in binary (2 in decimal)
7. 零填充右移 (>>>
)
- 用法:将作数的位向右移动指定的位置数,用零填充最左边的位(零填充)。
- 示例:
let a = -5; // 11111111111111111111111111111011 in binary (two's complement representation)
let result = a >>> 1; // 01111111111111111111111111111101 in binary (2147483645 in decimal)
常见陷阱和最佳实践
-
理解 2 的补码表示:
- 陷阱:误解负数如何用二进制(二进制补码)表示。
- 最佳实践: 熟悉 2 的补码表示。
- 例:
let a = -5; let result = ~a; // 4 (not -6, due to two's complement)
-
对非整数值进行按位运算:
- 陷阱:按位运算符将作数转换为 32 位整数,这可能会导致非整数值的意外结果。
- 最佳实践:在执行按位运算之前,请确保作数是整数。
- 例:
let a = 5.5; let result = a | 0; // 5 (bitwise OR with 0 truncates the decimal part)
-
右移 (
>>
) 中的符号传播:- 陷阱:右移 () 会保留符号位,这可能会导致负数出现意外结果。
>>
- 最佳实践:如果您不想保留符号位,请使用零填充右 shift ()。
>>>
- 例:
let a = -5; let result = a >> 1; // -3 (sign bit preserved) let result2 = a >>> 1; // 2147483645 (zero-filled)
- 陷阱:右移 () 会保留符号位,这可能会导致负数出现意外结果。
总结
按位运算符是用于对二进制数据进行低级作的强大工具。了解它们的行为和潜在陷阱可以帮助您在代码中有效地使用它们。
在 JavaScript 中对负数执行右移时,了解如何处理符号位非常重要。JavaScript 对负数使用 2 的补码表示,这会影响右移运算符的行为。
算术右移 (>>
)
算术右移运算符 () 在移位时保留符号位(最左边的位)。这意味着数字的符号保持不变,最左边的位填充了符号位(1 表示负数)。>>
例:
让我们取负数并执行 1 位的算术右移。-5
- -5 的二进制表示形式(在 32 位 2 补码中):
11111111111111111111111111111011
- 右移 1:
Original: 11111111111111111111111111111011
Shifted: 11111111111111111111111111111101
- 结果: 生成的二进制数为 ,以十进制表示。
11111111111111111111111111111101
-3
因此,结果为 。-5 >> 1
-3
逻辑右移 (>>>
)
逻辑右移运算符 () 不保留符号位。相反,它会用零填充最左边的位,从而有效地将数字视为无符号整数。>>>
例:
让我们取负数并执行 1 个位置的逻辑右移。-5
- -5 的二进制表示形式(在 32 位 2 补码中):
11111111111111111111111111111011
- 右移 1:
Original: 11111111111111111111111111111011
Shifted: 01111111111111111111111111111101
- 结果: 生成的二进制数为 ,以十进制表示。
01111111111111111111111111111101
2147483645
因此,结果为 。-5 >>> 1
2147483645
总结
- 算术右移 (
>>
):保留符号位,保持数字的符号。 - 逻辑右移 (
>>>
):不保留符号位,将数字视为无符号整数。
2 的补码是一种以二进制形式表示有符号整数的方法。它广泛用于计算机系统,因为它简化了算术电路的设计并允许轻松检测溢出。以下是它的工作原理:
2 补码的基础
- 正数:正整数的表示方式与标准二进制表示法相同。
- 负数:负整数的表示方式是将数字的绝对值(按位 NOT)的所有位反转,然后将结果加 1。
找到 2 的补码的步骤
让我们举个例子来说明将正数转换为其 2 的补码表示的步骤:
示例:在 2 的补码中表示 -5(8 位表示)
- Start with the positive Number(以正数开头):编写正数 (5) 的二进制表示形式。
00000101 (binary for 5)
- 反转位:翻转所有位(按位 NOT)。
11111010
- 加 1:将 1 加到倒置的位。
11111010
+ 1
--------
11111011
因此,在 8 位系统中 -5 的 2 补码表示为 。11111011
验证 2 的补码
要验证 2 的补码表示形式,您可以将其转换回十进制数:
- Invert the Bits:翻转 2 的补码表示的所有位。
11111011 (original)
00000100 (inverted)
- 加 1:将 1 加到倒置的位。
00000100
+ 1
--------
00000101
- 转换为十进制:结果是 ,由于我们从负数开始,因此原始数字是 。
5
-5
2's 补码的优势
- 零的单一表示形式:与其他方法(例如,符号幅度)不同,2 的补码只有一种表示零。
- 简化算术:加法、减法和乘法被简化,因为相同的二进制加法规则适用于正数和负数。
- 溢出检测:通过检查符号位的进位和进出,可以很容易地检测到溢出。
总结
2 的补码是一种广泛使用的方法,用于以二进制形式表示有符号整数。它简化了算术运算,并提供了一种处理正数和负数的一致方法。理解 2 的补码是使用二进制算术和计算机系统的基础。
7. TypeOf 运算符JavaScript
中的运算符用于确定给定变量或表达式的类型。它返回一个字符串,指示作数的类型。以下是它的工作原理:typeof
语法
typeof operand
- operand:要确定其类型的变量或表达式。
示例和返回值
以下是将运算符与不同类型值一起使用的一些示例:typeof
- 数字:
let num = 42;
console.log(typeof num); // "number"
- 字符串:
let str = "Hello, world!";
console.log(typeof str); // "string"
- 布尔值:
let bool = true;
console.log(typeof bool); // "boolean"
- 未定义:
let undef;
console.log(typeof undef); // "undefined"
- 空值:
let n = null;
console.log(typeof n); // "object" (this is a known quirk in JavaScript)
- 对象:
let obj = { name: "Alice" };
console.log(typeof obj); // "object"
- 数组:
let arr = [1, 2, 3];
console.log(typeof arr); // "object" (arrays are a type of object)
- 功能:
function greet() {
return "Hello!";
}
console.log(typeof greet); // "function"
- 符号:
let sym = Symbol("id");
console.log(typeof sym); // "symbol"
-
BigInt 的:
let bigInt = 123n; console.log(typeof bigInt); // "bigint"
常见陷阱和最佳实践
-
Null 类型:
- Pitfall: returns ,这可能会产生误导。
typeof null
"object"
- 最佳实践:使用严格相等性检查 .
null
- 例:
let n = null; console.log(n === null); // true
- Pitfall: returns ,这可能会产生误导。
-
数组和对象:
- Pitfall:数组和对象的返回值。
typeof
"object"
- 最佳实践:用于检查数组。
Array.isArray()
- 例:
let arr = [1, 2, 3]; console.log(Array.isArray(arr)); // true
- Pitfall:数组和对象的返回值。
-
功能:
- Pitfall:正确识别函数,但在将其与行为类似于函数的对象一起使用时要小心。
typeof
- 最佳实践:确保在其中检查类型的上下文。
- 例:
function greet() { return "Hello!"; } console.log(typeof greet); // "function"
- Pitfall:正确识别函数,但在将其与行为类似于函数的对象一起使用时要小心。
总结
运算符是确定 JavaScript 中变量或表达式类型的有用工具。但是,了解它的怪癖很重要,例如 和 数组的结果。通过了解这些细微差别,您可以在代码中有效地使用。
JavaScript 中的 and 运算符都用于确定变量的类型,但它们的用途不同,行为也不同。这是一个详细的比较:typeof
"object"
null
typeof
typeof
instanceof
typeof
算子
- 用途:确定变量或表达式的类型。
- 返回值:返回一个指示类型的字符串。
- 用法:用于检查原始数据类型。
- 语法:
typeof operand
- 示例:
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (quirk)
console.log(typeof {}); // "object"
console.log(typeof []); // "object" (arrays are objects)
console.log(typeof function() {}); // "function"
instanceof
算子
- 用途:确定对象是否为特定构造函数或类的实例。
- 返回值:返回布尔值 ( 或 )。
true
false
- 用法:用于检查对象和实例的类型。
- 语法:
object instanceof constructor
- 示例:
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (arrays are objects)
let date = new Date();
console.log(date instanceof Date); // true
console.log(date instanceof Object); // true
function Person(name) {
this.name = name;
}
let person = new Person("Alice");
console.log(person instanceof Person); // true
console.log(person instanceof Object); // true
主要区别
-
使用范围:
typeof
:主要用于检查原始数据类型(例如,数字、字符串、布尔值、undefined、symbol、bigint)。instanceof
:用于检查对象是否为特定构造函数或类的实例。
-
返回值:
typeof
:返回一个指示类型的字符串。instanceof
:返回一个布尔值,指示对象是否为构造函数的实例。
-
null 的
处理:
typeof
:返回 (一个已知的怪癖)。"object"
null
instanceof
:不能与 (如果使用) 引发错误。null
-
检查数组:
typeof
:数组的返回值。"object"
instanceof
:可以准确检查对象是否为 的实例。Array
-
检查功能:
typeof
:函数的返回值。"function"
instanceof
:可以检查对象是否是 .Function
实例
用:typeof
let value = "hello";
if (typeof value === "string") {
console.log("Value is a string");
}
用:instanceof
let date = new Date();
if (date instanceof Date) {
console.log("Date is an instance of Date");
}
总结
typeof
:最适合检查原始数据类型和函数。instanceof
:最适合检查对象是否为特定构造函数或类的实例。
发表评论 取消回复