JavaScript?運(yùn)算符實(shí)用指南之從基礎(chǔ)到位運(yùn)算
本文全面解析 JavaScript 中的各種運(yùn)算符,包含豐富的代碼示例和詳細(xì)的知識點(diǎn)講解。
一、運(yùn)算符基礎(chǔ)概念
在 JavaScript 中,運(yùn)算符是用于執(zhí)行數(shù)據(jù)運(yùn)算的符號,而參與運(yùn)算的數(shù)據(jù)稱為操作數(shù)。
操作符類型
按操作數(shù)數(shù)量分類:
- 一元運(yùn)算符:只有一個操作數(shù),如
++、--、typeof、void - 二元運(yùn)算符:有兩個操作數(shù),如
+、-、*、/、=、&&、|| - 三元運(yùn)算符:有三個操作數(shù),即條件運(yùn)算符
? :
按功能分類:
- 算術(shù)運(yùn)算符
- 比較運(yùn)算符
- 邏輯運(yùn)算符
- 位運(yùn)算符
- 賦值運(yùn)算符
- 其他特殊運(yùn)算符
表達(dá)式與返回值
每個表達(dá)式都會產(chǎn)生一個運(yùn)算結(jié)果,稱為返回值,而返回值的類型稱為返回類型。
let a = 5; // 賦值表達(dá)式返回賦值的結(jié)果 let b = a + 3; // 算術(shù)表達(dá)式返回運(yùn)算結(jié)果 console.log(b); // 函數(shù)調(diào)用表達(dá)式返回undefined
知識點(diǎn): Chrome瀏覽器控制臺是REPL環(huán)境(Read-Eval-Print-Loop),會自動輸出表達(dá)式的返回值。
二、算術(shù)運(yùn)算符
JavaScript 提供以下算術(shù)運(yùn)算符:
+、-、*、/:基本四則運(yùn)算%:求余(取模)++、--:自增自減**:冪運(yùn)算(ES6引入)
2.1 算術(shù)運(yùn)算的特殊情況
數(shù)字運(yùn)算的不精確性:
console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // false
知識點(diǎn): 這是由于浮點(diǎn)數(shù)在計(jì)算機(jī)中的二進(jìn)制表示導(dǎo)致的精度問題,并非JavaScript獨(dú)有。
除數(shù)為0的情況:
console.log(5 / 0); // Infinity(正無窮) console.log(-5 / 0); // -Infinity(負(fù)無窮) console.log(0 / 0); // NaN(非數(shù)字) // 判斷特殊值 console.log(isNaN(0 / 0)); // true console.log(isFinite(5 / 0)); // false
知識點(diǎn):
isNaN()函數(shù)用于檢測一個值是否為NaNisFinite()函數(shù)用于檢測一個值是否為有限數(shù)typeof運(yùn)算符返回類型的字符串表示
2.2 類型轉(zhuǎn)換規(guī)則
非加號運(yùn)算符的轉(zhuǎn)換規(guī)則:
console.log(10 - true); // 9 (true轉(zhuǎn)換為1)
console.log(10 - "5"); // 5 ("5"轉(zhuǎn)換為5)
console.log(10 - "abc"); // NaN(轉(zhuǎn)換失?。?
console.log(10 - ""); // 10 (空字符串轉(zhuǎn)換為0)
console.log(10 - null); // 10 (null轉(zhuǎn)換為0)
console.log(10 - undefined); // NaN
// 對象轉(zhuǎn)換
let obj = {};
console.log(10 - obj); // NaN (obj→"[object Object]"→NaN)知識點(diǎn): 除加號外的算術(shù)運(yùn)算符會將非數(shù)字類型隱式轉(zhuǎn)換為數(shù)字類型。
加號運(yùn)算符的特殊規(guī)則:
// 一邊有字符串時進(jìn)行字符串拼接
console.log(10 + "5"); // "105"(數(shù)字轉(zhuǎn)換為字符串)
console.log(true + "abc"); // "trueabc"(布爾值轉(zhuǎn)換為字符串)
// 兩邊都沒有字符串但有對象
console.log(10 + {}); // "10[object Object]"(對象轉(zhuǎn)換為字符串)
// 兩邊都沒有字符串和對象
console.log(true + 5); // 6 (true轉(zhuǎn)換為1)
console.log(null + 5); // 5 (null轉(zhuǎn)換為0)知識點(diǎn): 加號運(yùn)算符在有字符串參與時會優(yōu)先進(jìn)行字符串拼接,否則進(jìn)行數(shù)學(xué)加法運(yùn)算。
三、自增和自減運(yùn)算符
自增(++)和自減(--)運(yùn)算符是一元運(yùn)算符,用于將變量的值增加或減少1。
3.1 前綴與后綴的區(qū)別
let x = 5; let y = x++; // 后綴:先賦值后自增 console.log(x, y); // 6, 5 let a = 5; let b = ++a; // 前綴:先自增后賦值 console.log(a, b); // 6, 6
知識點(diǎn): 前綴形式返回自增后的值,后綴形式返回自增前的值。
3.2 優(yōu)先級問題
運(yùn)算符優(yōu)先級從高到低:
++、--*、/、%+、-
let x = 5; let result = x++ * 2 + 3; // 5*2+3=13,然后x自增為6 console.log(result, x); // 13, 6
知識點(diǎn): 優(yōu)先級決定了表達(dá)式中運(yùn)算的執(zhí)行順序,同級運(yùn)算符從左到右計(jì)算。
四、比較運(yùn)算符
比較運(yùn)算符用于比較兩個值,返回布爾值(true或false)。
4.1 大小比較運(yùn)算符
>、<、>=、<=
比較規(guī)則詳解:
// 字符串比較(按字符編碼逐位比較)
console.log("a" < "b"); // true(字符a的編碼小于b)
console.log("2" > "10"); // true(字符"2"編碼大于"1")
// 類型不同時轉(zhuǎn)換為數(shù)字比較
console.log("10" > 5); // true ("10"轉(zhuǎn)換為10)
console.log("abc" > 5); // false ("abc"轉(zhuǎn)換為NaN)
// 特殊值比較規(guī)則
console.log(NaN > 5); // false(NaN與任何值比較都是false)
console.log(Infinity > 1000); // true(無窮大比任何有限數(shù)大)
console.log(-Infinity < -1000); // true(負(fù)無窮比任何有限數(shù)?。?
// 對象比較(先轉(zhuǎn)換為原始類型)
let obj1 = {}, obj2 = {};
console.log(obj1 > obj2); // false (轉(zhuǎn)換為"[object Object]")
console.log(obj1 == obj2); // false (比較的是引用地址)知識點(diǎn):
- 字符串比較基于Unicode編碼值
- NaN與任何值(包括自身)比較都返回false
- 對象比較時先調(diào)用
valueOf()或toString()方法轉(zhuǎn)換為原始類型
4.2 相等比較運(yùn)算符
==、!=、===、!==
==和!=的隱式類型轉(zhuǎn)換規(guī)則:
// null和undefined的特殊規(guī)則
console.log(null == undefined); // true(它們只與彼此相等)
console.log(null == 0); // false(null只與undefined相等)
// 類型不同時的數(shù)字轉(zhuǎn)換
console.log("5" == 5); // true(字符串轉(zhuǎn)換為數(shù)字)
console.log(true == 1); // true(布爾值轉(zhuǎn)換為數(shù)字)
console.log("" == 0); // true(空字符串轉(zhuǎn)換為0)
// NaN的特殊性
console.log(NaN == NaN); // false(NaN不等于任何值,包括自身)
// 對象比較引用地址
console.log({} == {}); // false(不同的對象實(shí)例)知識點(diǎn): ==運(yùn)算符會進(jìn)行類型轉(zhuǎn)換,遵循復(fù)雜的轉(zhuǎn)換規(guī)則。
===和!==的嚴(yán)格比較:
// 嚴(yán)格相等要求值和類型都相同
console.log("5" === 5); // false(類型不同)
console.log(5 === 5); // true(值和類型都相同)
// 特殊值的嚴(yán)格比較
console.log(NaN === NaN); // false
console.log(null === undefined); // false
console.log(0 === -0); // true(特殊情況)知識點(diǎn):
===不進(jìn)行類型轉(zhuǎn)換,直接比較值和類型- 在實(shí)際開發(fā)中推薦使用
===和!==,避免隱式轉(zhuǎn)換帶來的意外結(jié)果
五、邏輯運(yùn)算符
邏輯運(yùn)算符用于布爾運(yùn)算,但也可以用于非布爾值,返回的不一定是布爾值。
5.1 邏輯與(&&)
// 布爾運(yùn)算
console.log(true && false); // false
// 短路特性:如果第一個操作數(shù)為假,直接返回,不計(jì)算第二個
console.log(false && console.log("不會執(zhí)行")); // false
// 非布爾值運(yùn)算:返回第一個為假的值,或最后一個為真的值
console.log(0 && "abc"); // 0(第一個假值)
console.log("abc" && 123); // 123(最后一個真值)
console.log(null && "abc"); // null(第一個假值)知識點(diǎn):
- 邏輯與的短路特性可用于條件執(zhí)行
- 返回的是操作數(shù)本身,不是強(qiáng)制轉(zhuǎn)換為布爾值
5.2 邏輯或(||)
// 布爾運(yùn)算
console.log(true || false); // true
// 短路特性:如果第一個操作數(shù)為真,直接返回,不計(jì)算第二個
console.log(true || console.log("不會執(zhí)行")); // true
// 非布爾值運(yùn)算:返回第一個為真的值,或最后一個為假的值
console.log(0 || "abc"); // "abc"(第一個真值)
console.log("abc" || 123); // "abc"(第一個真值)
console.log(null || undefined); // undefined(最后一個假值)知識點(diǎn): 邏輯或常用于設(shè)置默認(rèn)值
5.3 邏輯非(!)
// 對值進(jìn)行布爾取反 console.log(!true); // false console.log(!0); // true console.log(!"abc"); // false // 雙重非運(yùn)算可用于將值轉(zhuǎn)換為布爾類型 console.log(!!0); // false console.log(!!"abc"); // true
假值列表(以下值在布爾上下文中被視為false):
nullundefinedfalseNaN''(空字符串)0(包括+0和-0)
知識點(diǎn): 所有對象(包括空對象和數(shù)組)在布爾上下文中都被視為true。
六、條件(三目)運(yùn)算符
條件運(yùn)算符是JavaScript中唯一的三元運(yùn)算符。
// 基本語法:條件 ? 表達(dá)式1 : 表達(dá)式2
let age = 20;
let message = age >= 18 ? "成年人" : "未成年人";
console.log(message); // "成年人"
// 嵌套使用(可讀性較差,不建議過多嵌套)
let score = 85;
let grade = score >= 90 ? "優(yōu)秀" :
score >= 80 ? "良好" :
score >= 60 ? "及格" : "不及格";
console.log(grade); // "良好"知識點(diǎn):
- 條件運(yùn)算符是if-else語句的簡潔替代
- 過度嵌套會降低代碼可讀性,應(yīng)謹(jǐn)慎使用
七、位運(yùn)算符
位運(yùn)算符將操作數(shù)視為32位二進(jìn)制整數(shù)進(jìn)行運(yùn)算,小數(shù)部分會被截?cái)唷?/p>
7.1 位與(&)、位或(|)、位異或(^)
// 位與:兩位都為1時結(jié)果為1 console.log(5 & 3); // 1 (0101 & 0011 = 0001) // 位或:有一位為1時結(jié)果為1 console.log(5 | 3); // 7 (0101 | 0011 = 0111) // 位異或:兩位不同時結(jié)果為1 console.log(5 ^ 3); // 6 (0101 ^ 0011 = 0110)
知識點(diǎn): 位運(yùn)算前會將操作數(shù)轉(zhuǎn)換為32位整數(shù),小數(shù)部分被丟棄。
7.2 位非(~)和負(fù)數(shù)表示
// 位非:按位取反 console.log(~5); // -6 // 快速取整技巧 console.log(~~3.14); // 3 console.log(~~-2.7); // -2
知識點(diǎn):
- JavaScript使用二進(jìn)制補(bǔ)碼表示負(fù)數(shù)
~x等價于-x - 1~~可用于快速取整,效果類似Math.trunc()
7.3 位移運(yùn)算符
// 左移:<< (相當(dāng)于乘以2的n次方) console.log(5 << 2); // 20 (相當(dāng)于5*4) // 有符號右移:>> (相當(dāng)于除以2的n次方并取整) console.log(20 >> 2); // 5 (相當(dāng)于20/4) // 無符號右移:>>> (符號位也參與位移) console.log(-20 >>> 2); // 1073741819
知識點(diǎn):
- 左移n位相當(dāng)于乘以2?
- 右移n位相當(dāng)于除以2?并向下取整
- 無符號右移會將符號位當(dāng)作普通位處理
7.4 位運(yùn)算的實(shí)際應(yīng)用
權(quán)限控制系統(tǒng):
// 定義權(quán)限常量(使用2的冪次方)
const READ = 1; // 0001
const WRITE = 2; // 0010
const EXECUTE = 4; // 0100
const DELETE = 8; // 1000
// 用戶權(quán)限(使用位或組合權(quán)限)
let userPermissions = READ | WRITE; // 0011 (3)
// 檢查權(quán)限函數(shù)
function hasPermission(permissions, permission) {
return (permissions & permission) === permission;
}
console.log(hasPermission(userPermissions, READ)); // true
console.log(hasPermission(userPermissions, EXECUTE)); // false
// 添加權(quán)限(位或操作)
userPermissions |= EXECUTE;
console.log(hasPermission(userPermissions, EXECUTE)); // true
// 移除權(quán)限(位與和位非操作)
userPermissions &= ~WRITE;
console.log(hasPermission(userPermissions, WRITE)); // false知識點(diǎn): 位運(yùn)算在權(quán)限控制、標(biāo)志位處理等場景中非常高效。
八、其他重要運(yùn)算符
8.1 模板字符串運(yùn)算符
let name = "張三";
let age = 25;
// 使用反引號和${}插入表達(dá)式
console.log(`我叫${name},今年${age}歲`); // 我叫張三,今年25歲
console.log(`明年我就${age + 1}歲了`); // 明年我就26歲了知識點(diǎn): 模板字符串支持多行文本和表達(dá)式插值。
8.2 復(fù)合賦值運(yùn)算符
let x = 10; x += 5; // 等同于 x = x + 5 console.log(x); // 15 x **= 2; // 等同于 x = x ** 2 console.log(x); // 225 // 其他復(fù)合賦值運(yùn)算符 let y = 10; y -= 3; // y = 7 y *= 2; // y = 14 y /= 7; // y = 2 y %= 2; // y = 0
知識點(diǎn): 復(fù)合賦值運(yùn)算符是語法糖,使代碼更簡潔。
8.3 void運(yùn)算符
// void表達(dá)式總是返回undefined
console.log(void 0); // undefined
console.log(void (5 + 3)); // undefined
// 常用于立即執(zhí)行函數(shù)避免污染全局空間
void function() {
console.log("立即執(zhí)行函數(shù)");
}();
// 用于箭頭函數(shù)返回undefined
const doSomething = () => void console.log("執(zhí)行了");知識點(diǎn): void運(yùn)算符確保表達(dá)式執(zhí)行但返回undefined。
8.4 typeof運(yùn)算符
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" (歷史遺留問題)
console.log(typeof []); // "object"
console.log(typeof {}); // "object"
console.log(typeof function() {}); // "function"
// 括號可選
console.log(typeof(42)); // "number"
console.log(typeof 42); // "number"知識點(diǎn):
typeof null返回"object"是JavaScript著名的歷史bug- 函數(shù)有特殊的類型"function"
- 數(shù)組和普通對象都返回"object"
8.5 逗號運(yùn)算符
// 依次執(zhí)行表達(dá)式,返回最后一個表達(dá)式的值
let a = (1, 2, 3, 4);
console.log(a); // 4
// 用于for循環(huán)中的多個變量
for(let i = 0, j = 10; i < j; i++, j--) {
console.log(i, j);
}
// 在一行中執(zhí)行多個操作
let x = 0, y = 0, z = 0;
x = (y++, z++, y + z); // y和z自增,然后x賦值為y+z
console.log(x, y, z); // 2, 1, 1知識點(diǎn): 逗號運(yùn)算符優(yōu)先級最低,常用于需要在一行中執(zhí)行多個操作的場景。
九、求余與求模的區(qū)別
雖然JavaScript中的%運(yùn)算符被稱為"求模運(yùn)算符",但實(shí)際上它實(shí)現(xiàn)的是求余運(yùn)算。
求余(rem)與求模(mod)的數(shù)學(xué)區(qū)別:
- 求余:符號與被除數(shù)相同
- 求模:符號與除數(shù)相同
// 正數(shù)情況下兩者結(jié)果相同
console.log(5 % 3); // 2 (余數(shù))
// 5 rem 3 = 5 - 1*3 = 2 (商向0取整)
// 5 mod 3 = 5 - 1*3 = 2 (商向下取整)
// 負(fù)數(shù)情況下結(jié)果不同
console.log(-5 % 3); // -2 (余數(shù),符號與被除數(shù)-5相同)
// -5 rem 3 = -5 - (-1)*3 = -2 (商向0取整為-1)
// -5 mod 3 = -5 - (-2)*3 = 1 (商向下取整為-2)
// JavaScript沒有內(nèi)置的求模運(yùn)算,需要自行實(shí)現(xiàn)
function mod(n, m) {
return ((n % m) + m) % m;
}
console.log(mod(-5, 3)); // 1 (模數(shù),符號與除數(shù)3相同)知識點(diǎn): 在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,求余和求模是不同的概念,JavaScript的%實(shí)現(xiàn)的是求余運(yùn)算。
十、運(yùn)算符優(yōu)先級總結(jié)
JavaScript運(yùn)算符優(yōu)先級從高到低大致為:
- 成員訪問:
.[] - new(帶參數(shù)列表)
- 函數(shù)調(diào)用:
() - new(無參數(shù)列表)
- 后置遞增/遞減:
++-- - 邏輯非:
!位非:~typeof void delete await - 冪運(yùn)算:
** - 乘除取余:
*/% - 加減:
+- - 位移:
<<>>>>> - 關(guān)系比較:
<<=>>=ininstanceof - 相等比較:
==!====!== - 位與:
& - 位異或:
^ - 位或:
| - 邏輯與:
&& - 邏輯或:
|| - 條件運(yùn)算符:
? : - 賦值:
=+=-=等 - 逗號運(yùn)算符:
,
知識點(diǎn): 使用括號可以明確優(yōu)先級,提高代碼可讀性。
十一、綜合應(yīng)用示例
利用運(yùn)算符實(shí)現(xiàn)RGB顏色值的提?。?/strong>
function getRGBComponents(color) {
// 使用位移和位與提取顏色分量
let r = (color >> 16) & 0xFF; // 提取紅色分量
let g = (color >> 8) & 0xFF; // 提取綠色分量
let b = color & 0xFF; // 提取藍(lán)色分量
return [r, g, b];
}
let color = 0xFF3366; // 粉色
let [r, g, b] = getRGBComponents(color);
console.log(`R: ${r}, G: ${g}, B: $`); // R: 255, G: 51, B: 102安全的屬性訪問:
// 使用邏輯或設(shè)置默認(rèn)值
function getUserName(user) {
return user && user.name || "匿名用戶";
}
console.log(getUserName({name: "張三"})); // "張三"
console.log(getUserName(null)); // "匿名用戶"
// 使用可選鏈運(yùn)算符(ES2020)和空值合并運(yùn)算符(ES2020)
function getUserNameSafe(user) {
return user?.name ?? "匿名用戶";
}利用位運(yùn)算判斷奇偶性:
function isEven(num) {
return (num & 1) === 0; // 最后一位為0則是偶數(shù)
}
console.log(isEven(4)); // true
console.log(isEven(7)); // false總結(jié)
JavaScript提供了豐富的運(yùn)算符,從基本的算術(shù)運(yùn)算到復(fù)雜的位運(yùn)算,掌握這些運(yùn)算符的特性和使用場景對于編寫高效、簡潔的代碼至關(guān)重要。關(guān)鍵知識點(diǎn)包括:
- 理解隱式類型轉(zhuǎn)換:特別是在使用
==和+運(yùn)算符時 - 掌握運(yùn)算符優(yōu)先級:使用括號明確運(yùn)算順序,提高代碼可讀性
- 利用短路特性:
&&和||的短路特性可以簡化條件邏輯 - 位運(yùn)算的高效應(yīng)用:在權(quán)限控制、標(biāo)志位處理等場景中非常有用
- 推薦使用嚴(yán)格相等:
===和!==比==和!=更安全可靠 - 模板字符串的現(xiàn)代用法:簡化字符串拼接和插值
希望本文能幫助你全面理解JavaScript運(yùn)算符,并在實(shí)際開發(fā)中靈活運(yùn)用它們,寫出更優(yōu)雅、高效的代碼。
到此這篇關(guān)于JavaScript 運(yùn)算符完全指南:從基礎(chǔ)到位運(yùn)算的文章就介紹到這了,更多相關(guān)js位運(yùn)算內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript鼠標(biāo)滑動評分控件完整實(shí)例
這篇文章主要介紹了javascript鼠標(biāo)滑動評分控件實(shí)現(xiàn)方法,以完整實(shí)例形式詳細(xì)分析了javascript操作鼠標(biāo)事件及頁面元素樣式實(shí)現(xiàn)評分效果的方法,需要的朋友可以參考下2015-05-05
深入理解JavaScript系列(8) S.O.L.I.D五大原則之里氏替換原則LSP
本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實(shí)現(xiàn)的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。2012-01-01

