語(yǔ)法
- ECMAScript 中的一切(變量、函數(shù)名和操作符)都區(qū)分大小寫。
- JavaScript 語(yǔ)句結(jié)尾的分號(hào)(
;)不是必須的,但是建議任何時(shí)候都不要省略它。 - 建議始終在控制語(yǔ)句中使用代碼塊,即使代碼塊中只有一條語(yǔ)句。
標(biāo)識(shí)符
標(biāo)識(shí)符的定義:變量、函數(shù)、屬性的名字,或者函數(shù)的參數(shù)。
標(biāo)識(shí)符命名規(guī)則:
- 第一個(gè)字符,必須是任意 Unicode 字母(包括英文字母和其他語(yǔ)言的字母)、美元符號(hào)(
$)或下劃線(_)。 - 第二個(gè)字符及后面的字符,除了 Unicode 字母、美元符號(hào)和下劃線,還可以用數(shù)字
0-9。
最佳實(shí)踐:ECMAScript 標(biāo)識(shí)符采用駝峰大小寫格式。
注釋
單行注釋:
// 單行注釋內(nèi)容
塊級(jí)注釋/多行注釋:
/*
* 這是一個(gè)多行
* (塊級(jí))注釋
*/
嚴(yán)格模式
嚴(yán)格模式為 JavaScript 定義了一種不同的解析與執(zhí)行模型。在嚴(yán)格模式中,ECMAScript 3 中一些不確定的行為將得到處理,而且對(duì)某些不安全的操作也會(huì)拋出錯(cuò)誤。
- 整個(gè)腳本啟用嚴(yán)格模式,在文件頂部添加:
"use strict"
該語(yǔ)法是一個(gè)編譯指示,用于告訴支持的 JavaScript 引擎切換到嚴(yán)格模式。
- 函數(shù)體內(nèi)啟用嚴(yán)格模式:
function doSomething() {
"use strict";
// 函數(shù)體
}
關(guān)鍵字和保留字
不要使用關(guān)鍵字和保留字作為標(biāo)識(shí)符、屬性名或者函數(shù)名。
關(guān)鍵字:
break
case
catch
continue
default
delete
debugger (第 5 版新增)
do
else
finally
for
function
if
in
instanceof
new
return
switch
this
throw
try
typeof
var
void
while
with
保留字:
abstract
boolean
byte
char
class
const
debugger
double
enum
export
extends
final
float
goto
implements
import
int
interface
long
native
package
private
protected
public
short
static
super
synchronized
throws
transient
volatile
let
yield
變量
ECMAScript 的變量是松散類型/動(dòng)態(tài)類型的,松散類型可以保存任何類型的數(shù)據(jù)。換句話說,每個(gè)變量?jī)H僅是一個(gè)用于保存值的占位符而已。定義變量時(shí)要使用 var 操作符。
也就是說,變量的類型沒有限制,變量可以隨時(shí)更改類型。
- 使用
var操作符定義的變量將成為定義該變量的作用域中的局部變量。
function test() {
var message = "hello"; // 局部變量
}
test();
console.log(message); // 錯(cuò)誤!函數(shù)退出后,變量已經(jīng)被銷毀了!
- 省略
var操作符會(huì)創(chuàng)建全局變量。
/*
* 不推薦!
* 嚴(yán)格模式下會(huì)報(bào)錯(cuò):ReferenceError: message is not defined
*/
function test() {
message = "hello"; // 全局變量
}
test();
console.log(message); // "hello"
- 可以使用一條語(yǔ)句定義多個(gè)變量,用逗號(hào)分隔開。
// 代碼中的換行和變量縮進(jìn)不是必須的,但這樣做可以提高代碼可讀性。
var message = "hello",
found = false,
age = 24;
變量提升
JavaScript 引擎的工作方式是:先解析代碼,獲取所有被聲明的變量,然后再一行一行地運(yùn)行。這樣的結(jié)果就是:所有的變量的聲明語(yǔ)句,都會(huì)被提升到代碼的頭部,這就叫做變量提升(hoisting)。
console.log(a); // undefined
var a = 1;
上面代碼首先使用 console.log 方法,在控制臺(tái)(console)顯示變量 a 的值。這時(shí)變量 a 還沒有聲明和賦值,所以這是一種錯(cuò)誤的做法,但是實(shí)際上不會(huì)報(bào)錯(cuò)。因?yàn)榇嬖谧兞刻嵘龣C(jī)制,真正運(yùn)行的是下面的代碼:
var a;
console.log(a); // undefined
a = 1;
最后的結(jié)果是顯示 undefined,表示變量 a 已聲明,但還未賦值。
數(shù)據(jù)類型

Object 本質(zhì)上是由一組無(wú)序的鍵值對(duì)組成的。另外值得注意的是,JavaScript 中的函數(shù)是對(duì)象,函數(shù)名只是指向該對(duì)象的指針。
typeof 操作符
typeof 操作符:檢測(cè)并返回給定變量的數(shù)據(jù)類型。
| typeof 操作符返回的字符串 | 描述 |
|---|---|
| "undefined" | 未定義 |
| "boolean" | 布爾值 |
| "string" | 字符串 |
| "number" | 數(shù)值 |
| "object" | 對(duì)象或 null |
| "function" | 函數(shù) |
用 typeof 操作符檢測(cè)變量的數(shù)據(jù)類型:
var message = 'some string';
console.log(typeof message); // string
console.log(typeof 95); // number
// undefined 表示 value 變量沒有聲明,或者聲明了但是沒有賦初始化值。
console.log(typeof value); // undefined
?? 用 typeof 檢查 null 類型返回 object:
typeof null // "object"
null 的類型是 object,這是由于歷史原因造成的。1995 年的 JavaScript 語(yǔ)言第一版,只設(shè)計(jì)了五種數(shù)據(jù)類型(對(duì)象、整數(shù)、浮點(diǎn)數(shù)、字符串和布爾值),沒考慮 null,只把它當(dāng)作 object 的一種特殊值。后來(lái) null 獨(dú)立出來(lái),作為一種單獨(dú)的數(shù)據(jù)類型,為了兼容以前的代碼,typeof null 返回 object 就沒法改變了。
typeof 是一個(gè)操作符而不是函數(shù)
var message = "some string";
console.log(typeof message); // string
console.log(typeof (message)); // string
-
typeof操作符的操作數(shù)可以是變量(message),也可以是數(shù)值字面量。 -
typeof是一個(gè)操作符而不是函數(shù),所以圓括號(hào)盡管可以使用,但不是必需的。
typeof 與 instanceof 的使用異同
-
typeof操作符是確定一個(gè)變量是字符串、數(shù)值、布爾值,還是undefined的最佳工具(檢測(cè)基本類型)。 - 如果變量是給定引用類型(根據(jù)它的原型鏈來(lái)識(shí)別)的實(shí)例,
instanceof操作符返回true,而所有基本類型返回false(檢測(cè)引用類型)。
確定一個(gè)值是哪種基本類型可以使用
typeof操作符;
確定一個(gè)值是哪種引用類型可以使用instanceof操作符。
Undefined 類型
- 在使用
var聲明變量但未對(duì)其進(jìn)行初始化時(shí),這個(gè)變量的默認(rèn)值就是undefined。 -
undefined是一個(gè)特殊的值,表示“未定義”。 - 對(duì)未初始化和未聲明的變量執(zhí)行
typeof操作符都會(huì)返回undefined。
未聲明變量&未初始化變量的區(qū)別
var message; // 變量聲明后,如果未賦初始值,則默認(rèn)值為 undefined
alert(message); // "undefined"
alert(age); // 沒有聲明的變量直接使用會(huì)產(chǎn)生錯(cuò)誤!
// ?? 沒有聲明過的變量只能使用 typeof 操作符檢測(cè)其數(shù)據(jù)類型
alert(typeof message); // "undefined"
alert(typeof age) // "undefined"
undefined 常用場(chǎng)景
// 變量聲明了,但沒有賦值
var i;
i // undefined
// 調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于 undefined
function f(x) {
return x;
}
f() // undefined
// 對(duì)象沒有賦值的屬性
var o = new Object();
o.p // undefined
// 函數(shù)沒有返回值時(shí),默認(rèn)返回 undefined
function f() {}
f() // undefined
??
即便未初始化的變量會(huì)自動(dòng)被賦予undefined值,但顯式地初始化變量依然是明智的選擇。如果能夠做到這一點(diǎn),那么當(dāng)typeoft操作符返回undefined值時(shí),我們就知道被檢測(cè)的變量還沒有被聲明,而不是尚未初始化。
Null 類型
- Null 類型只有一個(gè)值
null。null值表示一個(gè)空對(duì)象指針。因此,typeof null會(huì)返回 "object"。 -
null表示“空值”,即該處的值現(xiàn)在為空。調(diào)用函數(shù)時(shí),某個(gè)參數(shù)未設(shè)置任何值,這時(shí)就可以傳入null,表示該參數(shù)為空。
空對(duì)象指針&未經(jīng)初始化變量
// 不推薦使用 undefined 顯式初始化變量,因?yàn)樗J(rèn)就是 undefined。
// 而且,字面值 undefined 的主要目的是用于比較。
var message = undefined; // ?
var message; // ?
// 但是如果定義的變量是對(duì)象,那么最好將該變量初始化為 null 而不是其他值。
var car = null; // ?
alert(typeof car); // "object"
// 實(shí)際上,undefined 值派生自 null 值
alert(null == undefined); // true
Null 類型 & Undefined 類型的區(qū)別
- Null 類型只有一個(gè)值
null,而 Undefined 類型只有一個(gè)值undefined; -
null是一個(gè)表示 “空” 的對(duì)象,轉(zhuǎn)為數(shù)值時(shí)為0; -
undefined是一個(gè)表示 "此處無(wú)定義" 的原始值,轉(zhuǎn)為數(shù)值時(shí)為NaN。
參考:InfoQ:如何在 JavaScript 中處理 null 和 undefined?
Boolean 類型
- Boolean 類型只有兩個(gè)字面值:
true和false。 - 通常意義上來(lái)說,0 為假,非 0 為真。但是在 Boolean 類型中,
true不一定等于 1,而false也不一定等于 0。 -
true和false區(qū)分大小寫。
轉(zhuǎn)型函數(shù):Boolean()
ECMAScript 中所有類型的值都有與這兩個(gè) Boolean 類型的值等價(jià)的值。要將一個(gè)值轉(zhuǎn)換為其對(duì)應(yīng)的 Boolean 值,可以調(diào)用轉(zhuǎn)型函數(shù) Boolean()。
| 數(shù)據(jù)類型 | 轉(zhuǎn)換為 true 的值 |
轉(zhuǎn)換為 false 的值 |
|---|---|---|
| Boolean | true |
false |
| String | 任何非空字符串 | “” 或者 ''(空字符串) |
| Number | 任何非零數(shù)字值(包括無(wú)窮大) | 0 和 NaN |
| Object | 任何對(duì)象 | null |
| Undefined | —— | undefined |
注意:空數(shù)組([])和空對(duì)象({})對(duì)應(yīng)的布爾值,都是 true。
示例:將一個(gè)值轉(zhuǎn)換為其對(duì)應(yīng)的 Boolean 值:
var message = "Hello World";
var messageAsBoolean = Boolean(message);
console.log(messageAsBoolean); // true
var message = null;
var messageAsBoolean = Boolean(message);
console.log(messageAsBoolean); // false
Number 類型
- 與其他語(yǔ)言不同,ECMScript 沒有為整數(shù)和浮點(diǎn)數(shù)值分別定義不同的數(shù)據(jù)類型,Number 類型可用于表示所有數(shù)值。
- Number 類型使用 IEEE754 格式來(lái)表示整數(shù)和浮點(diǎn)數(shù)值。
- Number 類型支持的數(shù)值字面量格式:十進(jìn)制、八進(jìn)制、十六進(jìn)制。
- Number 類型中,八進(jìn)制在嚴(yán)格模式下無(wú)效。
// 十進(jìn)制
var intNum = 55;
// 八進(jìn)制,第一位必須為 0
var octalNum1 = 070 // 八進(jìn)制的56
// 如果八進(jìn)制的字面值超出了范圍(0~7),前導(dǎo)零將會(huì)被忽略,后面的數(shù)值將被當(dāng)作十進(jìn)制數(shù)值解析。
var octNum2 = 079; // 79
var octNum3 = 08; // 8
// 十六進(jìn)制,前兩位必須為 0x
var hexNum =0xA // 十六進(jìn)制的10
// 科學(xué)計(jì)數(shù)法(e 表示法)
var float Num = 3.125e7; // 31250000
var float Num = 3.125e-3; // 0.003125
// 自動(dòng)轉(zhuǎn)換為科學(xué)記數(shù)法的情況
// 【1】小數(shù)點(diǎn)前的數(shù)字多于 21 位。
1234567890123456789012
// 1.2345678901234568e+21
123456789012345678901
// 123456789012345680000
// 【2】小數(shù)點(diǎn)后緊跟6個(gè)以上的零,就自動(dòng)轉(zhuǎn)為科學(xué)計(jì)數(shù)法
0.0000003 // 3e-7
// 否則,就保持原來(lái)的字面形式
0.000003 // 0.000003
浮點(diǎn)數(shù)值
- 浮點(diǎn)數(shù)值中必須包含一個(gè)小數(shù)點(diǎn),并且小數(shù)點(diǎn)后面必須至少有一位數(shù)字。
- 由于保存浮點(diǎn)數(shù)值需要的內(nèi)存空間是保存整數(shù)值的兩倍,因此 ECMAScript 會(huì)不失時(shí)機(jī)地將浮點(diǎn)數(shù)值轉(zhuǎn)換為整數(shù)值。
var floatNum1 = 1.1; // 浮點(diǎn)數(shù) 1.1
var floatNum2 = 1.; // 小數(shù)點(diǎn)后面沒有數(shù)字,自動(dòng)解析為 1
var floatNum3 = 10.0 // 整數(shù),自動(dòng)解析為 10
- 浮點(diǎn)數(shù)值的最高精度是17位小數(shù),但在進(jìn)行算術(shù)計(jì)算時(shí)其精確度遠(yuǎn)遠(yuǎn)不如整數(shù)。
- 浮點(diǎn)數(shù)值計(jì)算會(huì)產(chǎn)生舍入誤差問題,因此,永遠(yuǎn)不要測(cè)試某個(gè)特定的浮點(diǎn)數(shù)值。
0.1 + 0.2 === 0.3 // false
// 實(shí)際上,0.1 + 0.2 = 0.30000000004
0.3 / 0.1
// 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1)
// false
數(shù)值范圍
- JavaScript 能夠表示的數(shù)值范圍為 21024 到 2-1023(開區(qū)間),超出這個(gè)范圍的數(shù)無(wú)法表示。
(2^{1024}, 2^{-1023})
- 如果某次計(jì)算的結(jié)果超出了 JavaScript 數(shù)值范圍(
Number.MIN_VALUE,Number.MAX_VALUE),那么這個(gè)數(shù)值會(huì)被自動(dòng)轉(zhuǎn)換為Infinity值。而Infinity值不是能夠參與計(jì)算的數(shù)值。
?????? isFinite():在參數(shù)位于最小與最大數(shù)值之間會(huì)返回 true。
JavaScript 內(nèi)部,所有數(shù)字都是以 64 位浮點(diǎn)數(shù)形式儲(chǔ)存,即使整數(shù)也是如此。所以,1 與 1.0 是相同的,是同一個(gè)數(shù)。
1 === 1.0 // true
這就是說,JavaScript 語(yǔ)言的底層根本沒有整數(shù),所有數(shù)字都是小數(shù)(64 位浮點(diǎn)數(shù))。容易造成混淆的是,某些運(yùn)算只有整數(shù)才能完成,此時(shí) JavaScript 會(huì)自動(dòng)把 64 位浮點(diǎn)數(shù),轉(zhuǎn)成 32 位整數(shù),然后再進(jìn)行運(yùn)算。
JavaScript 提供的有效數(shù)字最長(zhǎng)為 53 個(gè)二進(jìn)制位。精度最多只能到 53 個(gè)二進(jìn)制位,這意味著,絕對(duì)值小于 2 的 53 次方的整數(shù),即 - 253 到 253,都可以精確表示。
所以,簡(jiǎn)單的法則就是:JavaScript 對(duì)15位的十進(jìn)制數(shù)都可以精確處理。
Math.pow(2, 53)
// 輸出:9007199254740992
// 多出的三個(gè)有效數(shù)字(最后三位的 111)都會(huì)無(wú)法保存,變成 0。
9007199254740992111
// 9007199254740992000
NaN
-
NaN(Not a Number),非數(shù)值,表示 本來(lái)要返回?cái)?shù)值的操作數(shù)未返回?cái)?shù)值的情況(這樣就不會(huì)拋出錯(cuò)誤了)。 - 在 ECMAScript 中,任何數(shù)值除以 0 會(huì)返回
NaN,因此不會(huì)影響其他代碼的執(zhí)行。 - 任何涉及
NaN的操作都會(huì)返回NaN。 -
NaN與任何值都不相等,包括NaN本身。
?????? isNaN():確定傳入?yún)?shù)是否“不是數(shù)值”。無(wú)法被轉(zhuǎn)換為數(shù)值的值會(huì)返回 true。
// 不是數(shù)值/不能轉(zhuǎn)換為數(shù)值,返回 true
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false(10是一個(gè)數(shù)值)
console.log(isNaN("10")); // false (可以被轉(zhuǎn)換為數(shù)值10)
console.log(isNaN("blue")); // true (不能被轉(zhuǎn)換為數(shù)值)
console.log(isNaN(true)); // false (可以被轉(zhuǎn)換為數(shù)值1)
console.log(isNaN("true")); // true
// 對(duì)于空數(shù)組和只有一個(gè)數(shù)值成員的數(shù)組,isNaN 返回 false。
// 因?yàn)閮?nèi)部會(huì)默認(rèn)先用 Number() 函數(shù)進(jìn)行一次轉(zhuǎn)換再作判斷。
isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false
使用 isNaN 之前,最好判斷一下數(shù)據(jù)類型:
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
NaN 不是獨(dú)立的數(shù)據(jù)類型,而是一個(gè)特殊數(shù)值,它的數(shù)據(jù)類型依然屬于 Number,使用 typeof 運(yùn)算符可以看得很清楚。
typeof NaN // 'number'
NaN === NaN // false
Boolean(NaN) // false
isNaN() 也適用于對(duì)象。在基于對(duì)象調(diào)用 isNaN() 函數(shù)時(shí),會(huì)首先調(diào)用對(duì)象的 valueOf() 方法,然后確定該方法返回的值是否可以轉(zhuǎn)換為數(shù)值。如果不能,則基于這個(gè)返回值再調(diào)用 toString() 方法,再測(cè)試返回值。
數(shù)值轉(zhuǎn)換
-
Number()可以用于任何數(shù)據(jù)類型。 -
parseInt()、parseFloat()專門用于把字符串轉(zhuǎn)換成數(shù)值。
1. Number() ,任何數(shù)據(jù)類型 —> 數(shù)值
// Boolean
var num1 = Number(true); // 1
var num2 = Number(false); // 0
// 數(shù)字 —> 數(shù)字
// null -> 0
var num4 = Number(null); // 0
// undefined -> NaN
var num5 = Number(undefined); // NaN
// 字符串
var num6 = Number("Hello world!"); // NaN
var num7 = Number("000011"); // 11
var num8 = Number(""); // 空字符串返回 0
parseInt('42 cats') // 42
Number('42 cats') // NaN
// 對(duì)象 ——> 字符串 ——> 數(shù)字
// 1.自動(dòng)調(diào)用對(duì)象的 valueOf() 方法,再轉(zhuǎn)為數(shù)值;
// 2.自動(dòng)調(diào)用對(duì)象的 toString() 方法,再轉(zhuǎn)為數(shù)值;
2. parseInt(),字符串 —> 整數(shù)
在處理整數(shù)的時(shí)候更常用的是 parseInt() 函數(shù)。
parseInt() 函數(shù)在轉(zhuǎn)換字符串時(shí),更多的是看其是否符合數(shù)值模式。它會(huì)忽略字符串前面的空格,直至找到第一個(gè)非空格字符。
如果第一個(gè)字符不是數(shù)字字符或者負(fù)號(hào),parseInt() 就會(huì)返回 NaN;也就是說,用 parseInt() 轉(zhuǎn)換空字符串會(huì)返回 NaN(Number() 對(duì)空字符返回 0)。
如果第一個(gè)字符是數(shù)字字符,parseInt()會(huì)繼續(xù)解析第二個(gè)字符,直到解析完所有后續(xù)字符或者遇到了一個(gè)非數(shù)字字符。
// 如果字符串頭部有空格,空格會(huì)被自動(dòng)去除。
parseInt(' 81') // 81
// 轉(zhuǎn)換字符串
var num1 = parseInt("1234abcd"); // 1234
var num2 = parseInt("1a2b3c4d5e"); // 1
// parseInt() 會(huì)忽略小數(shù)點(diǎn),因?yàn)樾?shù)點(diǎn)是非數(shù)字字符。
var num3 = parseInt("22.5"); // 22
var num4 = parseInt("22.34.5"); // 22
// parseInt() 處理空字符串返回 NaN
var num5 = parseInt(""); // NaN
var num6 = Number(""); // 0
// 如果字符串以 0x 或 0X 開頭,parseInt 會(huì)將其按照十六進(jìn)制數(shù)解析。
parseInt('0x10') // 16
// 如果字符串以 0 開頭,將其按照 10 進(jìn)制解析。
parseInt('011') // 11
// 指定基數(shù)(即多少進(jìn)制)
var num1 = parseInt("10", 2); //2 – parsed as binary
var num2 = parseInt("10", 8); //8 – parsed as octal
var num3 = parseInt("10", 10); //10 – parsed as decimal
var num4 = parseInt("10", 16); //16 – parsed as hexadecimal
// 對(duì)于那些會(huì)自動(dòng)轉(zhuǎn)為科學(xué)計(jì)數(shù)法的數(shù)字,parseInt 會(huì)將科學(xué)計(jì)數(shù)法的表示方法視為字符串,因此導(dǎo)致一些奇怪的結(jié)果。
parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt('1e+21') // 1
parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8
// 科學(xué)計(jì)數(shù)法應(yīng)該使用 parseFloat()
parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
在 ECMAScript 5 JavaScript 引擎中,parseInt() 已經(jīng)不具有解析八進(jìn)制值的能力,因此前導(dǎo)的零會(huì)被認(rèn)為無(wú)效,從而將這個(gè)值當(dāng)成"70",結(jié)果就得到十進(jìn)制的 70。在 ECMAScript 5 中,即使是在非嚴(yán)格模式下也會(huì)如此。
var num = parseInt("070"); // 70
為了避免錯(cuò)誤的解析,建議無(wú)論在什么情況下都明確指定基數(shù):
var num = parseInt("070", 8); // 56
多數(shù)情況下,我們要解析的都是十進(jìn)制數(shù)值,因此始終將 10 作為第二個(gè)參數(shù)是非常必要的。
3. parseFloat(),字符串 —> 浮點(diǎn)數(shù)
var num1 = parseFloat("12345blue"); // 12345
var num2 = parseFloat("0xA"); // 0
var num3 = parseFloat("22.5"); // 22.5
// 字符串中的第一個(gè)小數(shù)點(diǎn)是有效的,而第二個(gè)小數(shù)點(diǎn)是無(wú)效的。
var num4 = parseFloat("22.34.5"); // 22.34
var num5 = parseFloat("0980.5"); // 980.5
var num6 = parseFloat("3.125e7"); // 31250000
// parseFloat 方法會(huì)自動(dòng)過濾字符串前導(dǎo)的空格。
parseFloat('\t\v\r12.34\n ') // 12.34
// 如果參數(shù)不是字符串,或者字符串的第一個(gè)字符不能轉(zhuǎn)化為浮點(diǎn)數(shù),則返回 NaN。
parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
-
parseFloat()與parseInt()的區(qū)別:parseFloat()中字符串中的第一個(gè)小數(shù)點(diǎn)是有效的。 -
parseFloat()與parseInt()的第二個(gè)區(qū)別:parseFloat()始終都會(huì)忽略前導(dǎo)零。 -
parseFloat()只解析十進(jìn)制值,因此十六進(jìn)制格式的字符串則始終會(huì)被轉(zhuǎn)換成 0。 - 如果字符串包含的是一個(gè)可解析為整數(shù)的數(shù)(沒有小數(shù)點(diǎn),或者小數(shù)點(diǎn)后都是零),
parseFloat()會(huì)返回整數(shù)。
總結(jié)
- 比較兩個(gè)數(shù)字是否相等(在指定的誤差范圍內(nèi)):
Number.EPSILON - 整數(shù)的安全范圍:(
Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER) - 判斷一個(gè)值是否位于最小數(shù)值與最大數(shù)值之間:
isFinite() - 檢測(cè)一個(gè)值是否是整數(shù):
Number.isInterger() - 檢測(cè)一個(gè)值是否是安全的整數(shù):
Number.isSafeInterger() - 判斷一個(gè)值是否不是一個(gè)數(shù)字、或是一個(gè)無(wú)效的數(shù)值(
NaN):Number.isNaN() - 無(wú)窮數(shù):
Infinity - 判斷兩個(gè)值是否絕對(duì)相等:
Object.is() - 另外,如果需要對(duì)大數(shù)值進(jìn)行數(shù)學(xué)運(yùn)算,目前需要借助相關(guān)工具庫(kù)。
String 字符串
String 類型用于表示由零或多個(gè) 16 位 Unicode 字符組成的字符序列,即字符串。字符串可以用雙引號(hào)(“)或者單引號(hào)(‘)表示。
由于 HTML 語(yǔ)言的屬性值使用雙引號(hào),所以很多項(xiàng)目約定 JavaScript 語(yǔ)言的字符串只使用單引號(hào)。
ECMAScript 中的字符串是不可變的,也就是說,字符串一旦創(chuàng)建,它們的值就不能改變。
Unicode 字符集
JavaScript 使用 Unicode 字符集。JavaScript 引擎內(nèi)部所有字符都用 Unicode 表示。
每個(gè)字符在 JavaScript 內(nèi)部都是以 16 位(即 2 個(gè)字節(jié))的 UTF-16 格式儲(chǔ)存。也就是說,JavaScript 的單位字符長(zhǎng)度固定為 16 位長(zhǎng)度,即 2 個(gè)字節(jié)。
JavaScript 對(duì) UTF-16 的支持是不完整的,由于歷史原因,只支持兩字節(jié)的字符,不支持四字節(jié)的字符。
對(duì)于碼點(diǎn)在 U+10000 到 U+10FFFF 之間的字符,JavaScript 總是認(rèn)為它們是兩個(gè)字符(length 屬性為 2)。所以處理的時(shí)候,必須把這一點(diǎn)考慮在內(nèi),也就是說,JavaScript 返回的字符串長(zhǎng)度可能是不正確的。
字符字面量/轉(zhuǎn)義序列
字符字面量會(huì)被作為一個(gè)字符來(lái)解析。

toString() 方法
??
null和undefined值沒有這個(gè)方法。
- 在調(diào)用數(shù)值的
toString()方法時(shí),可以傳遞一個(gè)參數(shù):指定輸出數(shù)值的基數(shù),默認(rèn)為十進(jìn)制轉(zhuǎn)換。 - 通過傳遞基數(shù),
toString()可以輸出以二進(jìn)制、八進(jìn)制、十六進(jìn)制,乃至其他任意有效進(jìn)制格式表示的字符串值。
var num = 10;
alert(num.toString()); //"10"
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
alert(num.toString(10)); //"10"
alert(num.toString(16)); //"a"
String () 方法
String () 函數(shù)可以將任何類型的值轉(zhuǎn)換為字符串。轉(zhuǎn)換規(guī)則如下:
- 如果值有
toString()方法,則調(diào)用該方法; - 如果值是
null,則返回"null"; - 如果值是
undefined,則返回"undefined"。
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); //"10"
alert(String(value2)); //"true"
alert(String(value3)); //"null"
alert(String(value4)); //"undefined"
length 屬性
length 屬性返回字符串的長(zhǎng)度,該屬性也是無(wú)法改變的。
var s = 'hello';
s.length // 5
s.length = 3;
s.length // 5
s.length = 7;
s.length // 5
上面代碼表示字符串的 length 屬性無(wú)法改變,但是不會(huì)報(bào)錯(cuò)。
Base64 編碼
JavaScript 原生提供兩個(gè) Base64 相關(guān)的方法。
-
btoa():任意值轉(zhuǎn)為 Base64 編碼; -
atob():Base64 編碼轉(zhuǎn)為原來(lái)的值;
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"
注意,這兩個(gè)方法不適合非 ASCII 碼的字符,會(huì)報(bào)錯(cuò)。
btoa('你好') // 報(bào)錯(cuò)
要將非 ASCII 碼字符轉(zhuǎn)為 Base64 編碼,必須中間插入一個(gè)轉(zhuǎn)碼環(huán)節(jié),再使用這兩個(gè)方法。
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
Object 類型
- ECMAScript 中的對(duì)象就是一組 “鍵值對(duì)”(key-value)的集合,是一種無(wú)序的復(fù)合數(shù)據(jù)集合。
- 創(chuàng)建自定義對(duì)象:創(chuàng)建
Object類型的實(shí)例并為其添加屬性和(或)方法。
// 通過 new 操作符創(chuàng)建對(duì)象。
var o = new Object();
// 定義一個(gè)對(duì)象,賦值給一個(gè)變量 obj,對(duì)象內(nèi)部包含兩個(gè)鍵值對(duì)。
var obj = {
foo: 'Hello',
bar: 'World'
};
在 ECMAScript 中,Object 是所有對(duì)象的基礎(chǔ),因此所有對(duì)象都具有下面這些基本的屬性和方法。
| 屬性或方法名 | 描述 |
|---|---|
Constructor |
保存著用于創(chuàng)建當(dāng)前對(duì)象的函數(shù)。 |
hasOwnProperty(propertyName) |
檢查給定的屬性在當(dāng)前對(duì)象實(shí)例中是否存在(而不是在實(shí)例的原型中)。 |
isPrototypeOf(object) |
檢查當(dāng)前對(duì)象是否是傳入對(duì)象的原型。 |
propertyIsEnumerable(propertyName) |
檢查給定的屬性是否能夠使用 for-in 來(lái)枚舉。 |
toLoacleString() |
返回對(duì)象的字符串表示,該字符串與執(zhí)行環(huán)境的地區(qū)對(duì)應(yīng)。 |
toString() |
返回對(duì)象的字符串表示。 |
valueOf() |
返回對(duì)象的字符串、數(shù)值或布爾值表示。 |
使用 for...in 循環(huán)枚舉對(duì)象的屬性
- 它遍歷的是對(duì)象所有可遍歷(enumerable)的屬性,會(huì)跳過不可遍歷的屬性。
- 它不僅遍歷對(duì)象自身的屬性,還遍歷繼承的屬性。
var person = { name: '老張' };
// 遍歷對(duì)象的屬性,也會(huì)遍歷繼承來(lái)的屬性
for (var key in person) {
// 判斷某個(gè)屬性是否為對(duì)象自身的屬性
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
數(shù)組
數(shù)組(array)是按次序排列的一組值。每個(gè)值的位置都有編號(hào)(從 0 開始),整個(gè)數(shù)組用方括號(hào)表示。
// 定義數(shù)組,同時(shí)賦初值
var arr = ['a', 'b', 'c'];
// 先定義,后賦值
var arr = [];
arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';
本質(zhì)上,數(shù)組屬于一種特殊的對(duì)象。typeof 運(yùn)算符會(huì)返回?cái)?shù)組的類型是 object。
typeof [1, 2, 3] // "object"
數(shù)組的 length 屬性
數(shù)組的 length 屬性,返回?cái)?shù)組的成員數(shù)量:
['a', 'b', 'c'].length // 3
數(shù)組的 length 屬性是可寫的。如果人為設(shè)置一個(gè)小于當(dāng)前成員個(gè)數(shù)的值,該數(shù)組的成員會(huì)自動(dòng)減少到 length 設(shè)置的值。
當(dāng) length 屬性設(shè)為大于數(shù)組個(gè)數(shù)時(shí),讀取新增的位置都會(huì)返回 undefined。
清空數(shù)組的一個(gè)有效方法,就是將 length 屬性設(shè)為 0。
for...in 循環(huán)和數(shù)組的遍歷
for...in 循環(huán)不僅可以遍歷對(duì)象,也可以遍歷數(shù)組,畢竟數(shù)組只是一種特殊對(duì)象。
var a = [1, 2, 3];
for (var i in a) {
console.log(a[i]);
}
// 1
// 2
// 3
但是,for...in 不僅會(huì)遍歷數(shù)組所有的數(shù)字鍵,還會(huì)遍歷非數(shù)字鍵。
var a = [1, 2, 3];
a.foo = true;
for (var key in a) {
console.log(key);
}
// 0
// 1
// 2
// foo
上面代碼在遍歷數(shù)組時(shí),也遍歷到了非整數(shù)鍵 foo。所以,不推薦使用 for...in 遍歷數(shù)組。
數(shù)組的遍歷可以考慮使用 for 循環(huán)或 while 循環(huán)。
var a = [1, 2, 3];
// for循環(huán)
for(var i = 0; i < a.length; i++) {
console.log(a[i]);
}
// while循環(huán)
var i = 0;
while (i < a.length) {
console.log(a[i]);
i++;
}
var l = a.length;
while (l--) {
console.log(a[l]);
}
數(shù)組的 forEach 方法,也可以用來(lái)遍歷數(shù)組:
var colors = ['red', 'green', 'blue'];
colors.forEach(function (color) {
console.log(color);
});
// red
// green
// blue
數(shù)組的空位
數(shù)組的空位是可以讀取的,返回 undefined。
var a = [, , ,];
a[1] // undefined
使用 delete 命令刪除一個(gè)數(shù)組成員,會(huì)形成空位,并且不會(huì)影響 length 屬性。
var a = [1, 2, 3];
delete a[1];
a[1] // undefined
a.length // 3
如果是空位,使用數(shù)組的 forEach 方法、for...in 結(jié)構(gòu)、以及 Object.keys 方法進(jìn)行遍歷,空位都會(huì)被跳過。
操作符
一元操作符:只能操作一個(gè)值的操作符。

1?? 遞增和遞減操作符
遞增和遞減操作符遵循的規(guī)則:
- 在應(yīng)用于一個(gè)包含有效數(shù)字字符的字符串時(shí),先將其轉(zhuǎn)換為數(shù)字值,再執(zhí)行加減 1 的操作。字符串變量變成數(shù)值變量。
- 在應(yīng)用于一個(gè)不包含有效數(shù)字字符的字符串時(shí),將變量的值設(shè)置為 NaN。 字符串變量變成數(shù)值變量。
- 在應(yīng)用于布爾值 false 時(shí),先將其轉(zhuǎn)換為 0 再執(zhí)行加減 1 的操作。布爾值變量變成數(shù)值變量。
- 在應(yīng)用于布爾值 true 時(shí),先將其轉(zhuǎn)換為 1 再執(zhí)行加減 1 的操作。布爾值變量變成數(shù)值變量。
- 在應(yīng)用于浮點(diǎn)數(shù)值時(shí),執(zhí)行加減 1 的操作。
- 在應(yīng)用于對(duì)象時(shí),先調(diào)用對(duì)象的
valueOf()方法,以取得一個(gè)可供操作的值。然后對(duì)該值應(yīng)用前述規(guī)則。如果結(jié)果是 NaN,則在調(diào)用toString()方法后再應(yīng)用前述規(guī)則。對(duì)象變量變成數(shù)值變量。
前置型操作符
++i、--i
執(zhí)行前置遞增和遞減操作時(shí),變量的值都是在語(yǔ)句被求值以前改變的。
var age = 29;
var anotherAge = --age + 2; // age 先執(zhí)行了減法操作
console.log(age); // 28
console.log(anotherAge); // 30
后置型操作符
i++、i--
后置型遞增和遞減操作是在包含它們的語(yǔ)句被求值之后才執(zhí)行的。
var age = 29;
var anotherAge = age-- + 2; // age 后執(zhí)行減法操作
console.log(age); // 28
console.log(anotherAge); // 31
2?? 一元加和減操作符
一元加和減操作符主要用于基本的算術(shù)運(yùn)算,也可以用于轉(zhuǎn)換數(shù)據(jù)類型。
一元加操作符
- 一元加操作符以一個(gè)加號(hào)(+)表示,放在數(shù)值前面,對(duì)數(shù)值不會(huì)產(chǎn)生任何影響。
- 當(dāng)一元加操作符作用于非數(shù)值時(shí),該操作符會(huì)像
Number()轉(zhuǎn)型函數(shù)一樣對(duì)這個(gè)值執(zhí)行轉(zhuǎn)換。
示例:a = +a;
一元減操作符
- 將一元減操作符應(yīng)用于數(shù)值時(shí),該值會(huì)變成負(fù)數(shù)。
- 當(dāng)一元減操作符作用于非數(shù)值時(shí),一元減操作符遵循與一元加操作符相同的規(guī)則,最后再將得到的數(shù)值轉(zhuǎn)換為負(fù)數(shù)。
示例:a = -a;
3?? 位操作符
- 位操作符按內(nèi)存中表示數(shù)值的位來(lái)操作數(shù)值。
- 位操作符并不直接操作 64 位的值。而是先將 64 位的值轉(zhuǎn)換成 32 位的整數(shù),然后執(zhí)行操作,最后再將結(jié)果轉(zhuǎn)換回 64 位。
- 默認(rèn)情況下,ECMAScript 中的所有整數(shù)都是有符號(hào)整數(shù)。
- 符號(hào)位:對(duì)于有符號(hào)的整數(shù),32 位中的前 31 位用于表示整數(shù)的值。第 32 位用于表示數(shù)值的符號(hào):0 表示正數(shù),1 表示負(fù)數(shù)。
- 負(fù)數(shù)同樣以二進(jìn)制碼存儲(chǔ),但使用的格式是二進(jìn)制補(bǔ)碼。
- 如果對(duì)非數(shù)值應(yīng)用位操作符,會(huì)先使用
Number()函數(shù)將該值轉(zhuǎn)換為一個(gè)數(shù)值(自動(dòng)完成),然后再應(yīng)用位操作。
在 ECMAScript 中,當(dāng)對(duì)數(shù)值應(yīng)用位操作符時(shí),后臺(tái)會(huì)發(fā)生如下轉(zhuǎn)換過程:
64 位的數(shù)值被轉(zhuǎn)換成 32 位數(shù)值,然后執(zhí)行位操作,最后再將 32 位的結(jié)果轉(zhuǎn)換回 64 位數(shù)值。
但這個(gè)轉(zhuǎn)換過程也導(dǎo)致了一個(gè)嚴(yán)重的副效應(yīng),即在對(duì)特殊的 NaN 和 Infinity 值應(yīng)用位操作時(shí),這兩個(gè)值都會(huì)被當(dāng)成 0 來(lái)處理。
1. 按位非(NOT)
按位非操作的本質(zhì):操作數(shù)的負(fù)值減 1。
var num1 = 25; //binary 00000000000000000000000000011001
var num2 = ~num1; //binary 11111111111111111111111111100110
alert(num2); //-26
2. 按位與(AND)
| 第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
按位與操作只在兩個(gè)數(shù)值的對(duì)應(yīng)位都是 1 時(shí)才返回 1,任何一位是 0,結(jié)果都是 0。
var result = 25 & 3;
alert(result); //outputs 1
// 按位與原理:11得1,01得0
// 25 = 0000 0000 0000 0000 0000 0000 0001 1001
// 3 = 0000 0000 0000 0000 0000 0000 0000 0011
// ----------------------------------------------
// AND = 0000 0000 0000 0000 0000 0000 0000 0001
3. 按位或(OR)
| 第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
var result = 25 | 3;
alert(result); //27
4. 按位異或(XOR)
| 第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
|---|---|---|
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
var result = 25 ^ 3;
alert(result); //26
5. 左移
左移(<<):將數(shù)值的所有位向左移動(dòng)指定的位數(shù)。
左移不會(huì)影響操作數(shù)的符號(hào)位。
6. 有符號(hào)右移
有符號(hào)右移(>>),保留符號(hào)位(即正負(fù)號(hào)標(biāo)記),用符號(hào)位的值來(lái)填充所有空位。
7. 無(wú)符號(hào)右移
無(wú)符號(hào)右移(>>>),用 0 來(lái)填充空位。對(duì)正數(shù)來(lái)說,無(wú)符號(hào)右移的結(jié)果與有符號(hào)右移相同。
無(wú)符號(hào)右移操作符會(huì)把負(fù)數(shù)的二進(jìn)制碼當(dāng)成正數(shù)的二進(jìn)制碼。
4?? 布爾操作符
布爾操作符一共有 3 個(gè):非(NOT)、與(AND)和或(OR)。
邏輯非 !
- 邏輯非操作符首先會(huì)將它的操作數(shù)轉(zhuǎn)換為一個(gè)布爾值,然后再對(duì)其求反。
- 同時(shí)使用兩個(gè)邏輯非操作符(!!),實(shí)際上就會(huì)模擬
Boolean()轉(zhuǎn)型函數(shù)的行為,即返回一個(gè)操作數(shù)的布爾值。
邏輯非操作符遵循下列規(guī)則:
- 如果操作數(shù)是一個(gè)對(duì)象,返回 false;
- 如果操作數(shù)是一個(gè)空字符串,返回 true;
- 如果操作數(shù)是一個(gè)非空字符串,返回 false;
- 如果操作數(shù)是數(shù)值 0,返回 true;
- 如果操作數(shù)是任意非 0 數(shù)值(包括 Infinity),返回 false;
- 如果操作數(shù)是
null,返回 true; - 如果操作數(shù)是
NaN,返回 true; - 如果操作數(shù)是
undefined,返回 true。
邏輯與 &&
邏輯與的真值表如下:
| 第一個(gè)操作數(shù) | 第二個(gè)操作數(shù) | 結(jié)果 |
|---|---|---|
true |
true |
true |
true |
false |
false |
false |
true |
false |
false |
false |
false |
邏輯與操作可以應(yīng)用于任何類型的操作數(shù),而不僅僅是布爾值。
在有一個(gè)操作數(shù)不是布爾值的情況下,邏輯與操作就不一定返回布爾值。此時(shí),它遵循下列規(guī)則:
- 如果第一個(gè)操作數(shù)是對(duì)象,則返回第二個(gè)操作數(shù);
- 如果第二個(gè)操作數(shù)是對(duì)象,則只有在第一個(gè)操作數(shù)的求值結(jié)果為 true 的情況下才會(huì)返回該對(duì)象;
- 如果兩個(gè)操作數(shù)都是對(duì)象,則返回第二個(gè)操作數(shù);
- 如果有一個(gè)操作數(shù)是
null,則返回null; - 如果有一個(gè)操作數(shù)是
NaN,則返回NaN; - 如果有一個(gè)操作數(shù)是
undefined,則返回undefined。
邏輯與操作屬于短路操作,即如果第一個(gè)操作數(shù)能夠決定結(jié)果,那么就不會(huì)再對(duì)第二個(gè)操作數(shù)求值。
不能在邏輯與操作中使用未定義的值。
邏輯或 ||
邏輯或的真值表如下:
| 第一個(gè)操作數(shù) | 第二個(gè)操作數(shù) | 結(jié)果 |
|---|---|---|
true |
true |
true |
true |
false |
true |
false |
true |
true |
false |
false |
false |
與邏輯與操作相似,如果有一個(gè)操作數(shù)不是布爾值,邏輯或也不一定返回布爾值;此時(shí),它遵循下列規(guī)則:
- 如果第一個(gè)操作數(shù)是對(duì)象,則返回第二個(gè)操作數(shù);
- 如果第一個(gè)操作數(shù)的求值結(jié)果為
false,則返回第二個(gè)操作數(shù); - 如果兩個(gè)操作數(shù)都是對(duì)象,則返回第一個(gè)操作數(shù);
- 如果兩個(gè)操作數(shù)都是
null,則返回null; - 如果兩個(gè)操作數(shù)都是
NaN,則返回NaN; - 如果兩個(gè)操作數(shù)都是
undefined,則返回undefined。
邏輯或操作符也是短路操作符。也就是說,如果第一個(gè)操作數(shù)的求值結(jié)果為 true,就不會(huì)對(duì)第二個(gè)操作數(shù)求值了。
短路操作
邏輯與/邏輯或操作屬于短路操作。
即:如果第一個(gè)操作數(shù)能夠決定結(jié)果,那么就不會(huì)再對(duì)第二個(gè)操作數(shù)求值。
可以利用邏輯或的這一行為來(lái)避免為變量賦 null 或 undefined 值:
var myObject = preferredObject || backupObject;
/*
* 變量 myObject 將被賦予等號(hào)后面兩個(gè)值中的一個(gè)。
* 變量 preferredObject 中包含優(yōu)先賦給變量 myObject 的值,
* 變量 backupObject 負(fù)責(zé)在 preferredObject 中不包含有效值的情況下提供后備值。
* 如果 preferredObject 的值不是 null,那么它的值將被賦給 myObject;
* 如果是 null,則將 backupObject 的值賦給 myObject。
*/
node.js 示例代碼:
// 組裝參數(shù)
const payload = ctx.request.body || {};
5?? 乘性操作符
- ECMAScript 定義了 3 個(gè)乘性操作符:乘法、除法和求模。
- 如果參與乘性計(jì)算的某個(gè)操作數(shù)不是數(shù)值,后臺(tái)會(huì)先使用
Number()轉(zhuǎn)型函數(shù)將其轉(zhuǎn)換為數(shù)值。
乘法 *
乘法用于計(jì)算兩個(gè)數(shù)值的乘積。
在處理特殊值的情況下,乘法操作符遵循下列特殊的規(guī)則:
- 如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的乘法計(jì)算,即兩個(gè)正數(shù)或兩個(gè)負(fù)數(shù)相乘的結(jié)果還是正數(shù),而如果只有一個(gè)操作數(shù)有符號(hào),那么結(jié)果就是負(fù)數(shù)。如果乘積超過了 ECMAScript 數(shù)值的表示范圍,則返回
Infinity或-Infinity; - 如果有一個(gè)操作數(shù)是
NaN,則結(jié)果是NaN; - 如果是
Infinity與 0 相乘,則結(jié)果是NaN; - 如果是
Infinity與非 0 數(shù)值相乘,則結(jié)果是Infinity或-Infinity,取決于有符號(hào)操作數(shù)的符號(hào); Infinity * Infinity = Infinity;- 如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺(tái)調(diào)用
Number()將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
除法 /
除法執(zhí)行第二個(gè)操作數(shù)除第一個(gè)操作數(shù)的計(jì)算。
除法操作符對(duì)特殊的值也有特殊的處理規(guī)則。這些規(guī)則如下:
- 如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的除法計(jì)算,即兩個(gè)正數(shù)或兩個(gè)負(fù)數(shù)相除的結(jié)果還是正數(shù),而如果只有一個(gè)操作數(shù)有符號(hào),那么結(jié)果就是負(fù)數(shù)。如果商超過了 ECMAScript 數(shù)值的表示范圍,則返回
Infinity或-Infinity; - 如果有一個(gè)操作數(shù)是
NaN,則結(jié)果是NaN; Infinity / Infinity = NaN;0 / 0 = NaN;- 如果是非零的有限數(shù)被零除,則結(jié)果是
Infinity或-Infinity,取決于有符號(hào)操作數(shù)的符號(hào); - 如果是
Infinity被任何非零數(shù)值除,則結(jié)果是Infinity或-Infinity,取決于有符號(hào)操作數(shù)的符號(hào); - 如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺(tái)調(diào)用
Number()將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
求模(取余數(shù)) %
求模操作符會(huì)遵循下列特殊規(guī)則來(lái)處理特殊的值:
- 如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的除法計(jì)算,返回除得的余數(shù);
- 如果被除數(shù)是無(wú)窮大值而除數(shù)是有限大的數(shù)值,則結(jié)果是
NaN; - 如果被除數(shù)是有限大的數(shù)值而除數(shù)是零,則結(jié)果是
NaN; Infinity % Infinity = NaN;- 如果被除數(shù)是有限大的數(shù)值而除數(shù)是無(wú)窮大的數(shù)值,則結(jié)果是被除數(shù);
- 如果被除數(shù)是零,則結(jié)果是零;
- 如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺(tái)調(diào)用
Number()將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
6?? 加性操作符
加法 +
(+0) + (+0) = (+0);
(-0) + (-0) = (-0);
(+0) + (-0) = (+0);
Infinity + Infinity = Infinity;
(-Infinity) + (-Infinity) = (-Infinity);
Infinity + (-Infinity) = NaN;
- 字符串 + 字符串 = 拼接字符串。
- 字符串 + 操作數(shù) = 操作數(shù)轉(zhuǎn)換為字符串,再拼接兩個(gè)字符串。
- 如果有一個(gè)操作數(shù)是
NaN,則結(jié)果是NaN; - 如果有一個(gè)操作數(shù)是對(duì)象、數(shù)值或布爾值,則調(diào)用它們的
toString()方法取得相應(yīng)的字符串值,然后再應(yīng)用前面關(guān)于字符串的規(guī)則。對(duì)于undefined和null,則分別調(diào)用String()函數(shù)并取得字符串"undefined"和"null"。
var result1 = 5 + 5;
console.log(result1); // 10
var result2 = 5 + "5";
console.log(result2); // 55
// 錯(cuò)誤示例
var num1 = 5;
var num2 = 10;
var message1 = "The sum of 5 and 10 is " + num1 + num2;
console.log(message1); // The sum of 5 and 10 is 510
// 正確示例
var num1 = 5;
var num2 = 10;
var message2 = "The sum of 5 and 10 is " + (num1 + num2);
console.log(message2); // The sum of 5 and 10 is 15
減法 -
(+0) - (+0) = (+0);
(+0) - (-0) = (-0);
(-0) - (-0) = (+0);
Infinity - Infinity = NaN;
(-Infinity) - (-Infinity) = NaN;
Infinity - (-Infinity) = Infinity;
(-Infinity) - Infinity = (-Infinity);
ECMAScript 中的減法操作符在處理各種數(shù)據(jù)類型轉(zhuǎn)換時(shí),同樣需要遵循一些特殊規(guī)則:
- 如果兩個(gè)操作符都是數(shù)值,則執(zhí)行常規(guī)的算術(shù)減法操作并返回結(jié)果;
- 如果有一個(gè)操作數(shù)是
NaN,則結(jié)果是NaN; - 如果有一個(gè)操作數(shù)是字符串、布爾值、
null或undefined,則先在后臺(tái)調(diào)用Number()函數(shù)將其轉(zhuǎn)換為數(shù)值,然后再根據(jù)前面的規(guī)則執(zhí)行減法計(jì)算。如果轉(zhuǎn)換的結(jié)果是NaN,則減法的結(jié)果就是NaN; - 如果有一個(gè)操作數(shù)是對(duì)象,則調(diào)用對(duì)象的
valueOf()方法以取得表示該對(duì)象的數(shù)值。如果得到的值是NaN,則減法的結(jié)果就是NaN。如果對(duì)象沒有valueOf()方法,則調(diào)用其toString()方法并將得到的字符串轉(zhuǎn)換為數(shù)值。
7?? 關(guān)系操作符
當(dāng)關(guān)系操作符的操作數(shù)使用了非數(shù)值時(shí),也要進(jìn)行數(shù)據(jù)轉(zhuǎn)換或完成某些奇怪的操作。以下就是相應(yīng)的規(guī)則。
- 如果兩個(gè)操作數(shù)都是數(shù)值,則執(zhí)行數(shù)值比較。
- 如果兩個(gè)操作數(shù)都是字符串,則比較兩個(gè)字符串對(duì)應(yīng)的字符編碼值。
- 如果一個(gè)操作數(shù)是數(shù)值,則將另一個(gè)操作數(shù)轉(zhuǎn)換為一個(gè)數(shù)值,然后執(zhí)行數(shù)值比較。
- 如果一個(gè)操作數(shù)是對(duì)象,則調(diào)用這個(gè)對(duì)象的
valueOf()方法,用得到的結(jié)果按照前面的規(guī)則執(zhí)行比較。如果對(duì)象沒有valueOf()方法,則調(diào)用toString()方法,并用得到的結(jié)果根據(jù)前面的規(guī)則執(zhí)行比較。 - 如果一個(gè)操作數(shù)是布爾值,則先將其轉(zhuǎn)換為數(shù)值,然后再執(zhí)行比較。
- 任何操作數(shù)與
NaN進(jìn)行比較,結(jié)果都是false。
// 兩個(gè)操作數(shù)都是字符串, 而字符串比較的是字符編碼("2"的字符編碼是 50,而"3"的字符編碼是 51)。
var result = "23" < "3" // true
// 字符串"23"會(huì)被轉(zhuǎn)換成數(shù)值 23,然后再與 3 進(jìn)行比較
var result = "23" < 3 // false
// 字母"a"不能轉(zhuǎn)換成合理的數(shù)值,因此就被轉(zhuǎn)換成了 NaN。
var result = "a" < 3; // false
8?? 相等操作符
- 相等和不相等——先轉(zhuǎn)換再比較;
- 全等和不全等——僅比較而不轉(zhuǎn)換;
相等(==)和不相等(!=)
在轉(zhuǎn)換不同的數(shù)據(jù)類型時(shí),相等和不相等操作符遵循下列基本規(guī)則:
- 如果有一個(gè)操作數(shù)是布爾值,則在比較相等性之前先將其轉(zhuǎn)換為數(shù)值——
false轉(zhuǎn)換為 0,而true轉(zhuǎn)換為 1。 - 如果一個(gè)操作數(shù)是字符串,另一個(gè)操作數(shù)是數(shù)值,在比較相等性之前先將字符串轉(zhuǎn)換為數(shù)值;
- 如果一個(gè)操作數(shù)是對(duì)象,另一個(gè)操作數(shù)不是,則調(diào)用對(duì)象的
valueOf()方法,用得到的基本類型值按照前面的規(guī)則進(jìn)行比較; -
null和undefined是相等的。 - 要比較相等性之前,不能將
null和undefined轉(zhuǎn)換成其他任何值。 - 如果有一個(gè)操作數(shù)是
NaN,則相等操作符返回false,而不相等操作符返回true。重要提示:即使兩個(gè)操作數(shù)都是NaN,相等操作符也返回false;因?yàn)榘凑找?guī)則,NaN不等于NaN。 - 如果兩個(gè)操作數(shù)都是對(duì)象,則比較它們是不是同一個(gè)對(duì)象。如果兩個(gè)操作數(shù)都指向同一個(gè)對(duì)象,則相等操作符返回
true;否則,返回false。
null == undefined // true,類似的值
null === undefined // false,不同類型的值
"NaN" == NaN // false
5 == NaN // false
NaN == NaN // false
NaN != NaN // true
false == 0 // true
true == 1 // true
true == 2 // false
undefined == 0 // false
null == 0 // false
"5" == 5 // true
全等(===)和不全等(!==)
- 相等(
==):如果兩個(gè)操作數(shù)類型不同,會(huì)自動(dòng)強(qiáng)制轉(zhuǎn)換為相等類型的操作數(shù),再進(jìn)行比較(強(qiáng)制轉(zhuǎn)型)。 - 全等(
===):兩個(gè)操作數(shù)未經(jīng)轉(zhuǎn)換就相等的情況下才返回true。
9?? 條件操作符
條件操作符也常稱為三元運(yùn)算符:
variable = boolean_expression ? true_value : false_value;
?? 賦值操作符 =
復(fù)合賦值操作符:在等于號(hào)(=)前面再添加乘性操作符、加性操作符或位操作符。
*=、/=、%=、+=、-=、<<=、>>=、>>>=、
復(fù)合賦值操作符可以簡(jiǎn)化賦值操作,但不會(huì)帶來(lái)任何性能的提升。
11. 逗號(hào)操作符
逗號(hào)操作符多用于聲明多個(gè)變量。
// 1.在一條語(yǔ)句中執(zhí)行多個(gè)操作,聲明多個(gè)變量
var num1=1, num2=2, num3=3;
// 2.賦值,總是返回表達(dá)式中的最后一項(xiàng)
var num = (5, 1, 4, 8, 0); // num 的值為 0
語(yǔ)句

if 語(yǔ)句
ECMAScript 會(huì)自動(dòng)調(diào)用 Boolean() 轉(zhuǎn)換函數(shù)將 if 表達(dá)式中的條件語(yǔ)句轉(zhuǎn)換為一個(gè)布爾值。
if (m === 0) {
// ...
} else if (m === 1) {
// ...
} else if (m === 2) {
// ...
} else {
// ...
}
switch 語(yǔ)句
ECMAScript 中 switch 的特點(diǎn):
- 可以在
switch語(yǔ)句中使用任何數(shù)據(jù)類型。 - 每個(gè)
case值可以是常量、變量、表達(dá)式。 -
switch語(yǔ)句在比較值時(shí)使用的是全等操作符(===),因此不會(huì)發(fā)生類型轉(zhuǎn)換。
while 語(yǔ)句
while 語(yǔ)句屬于前測(cè)試循環(huán)語(yǔ)句,也就是說,在循環(huán)體內(nèi)的代碼被執(zhí)行之前,就會(huì)對(duì)出口條件求值。因此,循環(huán)體內(nèi)的代碼有可能永遠(yuǎn)不會(huì)被執(zhí)行。
do-while 語(yǔ)句
do-while 語(yǔ)句是一種后測(cè)試循環(huán)語(yǔ)句,即只有在循環(huán)體中的代碼執(zhí)行之后,才會(huì)測(cè)試出口條件。換句話說,在對(duì)條件表達(dá)式求值之前,循環(huán)體內(nèi)的代碼至少會(huì)被執(zhí)行一次。
for 語(yǔ)句
for 語(yǔ)句也是一種前測(cè)試循環(huán)語(yǔ)句,但它具有在執(zhí)行循環(huán)之前初始化變量和定義循環(huán)后要執(zhí)行的代碼的能力。
由于 ECMAScript 中不存在塊級(jí)作用域,因此在循環(huán)內(nèi)部定義的變量也可以在外部訪問到。
// 即使 i 是在循環(huán)內(nèi)部定義的一個(gè)變量,但在循環(huán)外部仍然可以訪問到它。
var count = 10;
for (var i = 0; i < count; i++) {
console.log(i);
}
console.log(i); // 10
for-in 語(yǔ)句
如果表示要迭代的對(duì)象的變量值為 null 或 undefined,for-in 語(yǔ)句會(huì)拋出錯(cuò)誤,比如數(shù)組中間有一個(gè)對(duì)象為空。ECMAScript 5 更正了這一行為,對(duì)這種情況不再拋出錯(cuò)誤,而只是不執(zhí)行循環(huán)體。
?? 建議在使用 for-in 循環(huán)之前,先檢測(cè)確認(rèn)該對(duì)象的值不是 null 或 undefined。
label 語(yǔ)句
- JavaScript 語(yǔ)言可以在代碼中添加
label標(biāo)簽,相當(dāng)于定位符,用于跳轉(zhuǎn)到程序的任意位置。 - 標(biāo)簽通常與
break語(yǔ)句和continue語(yǔ)句配合使用,跳出特定的循環(huán)。 - 建議如果使用
label語(yǔ)句,一定要使用描述性的標(biāo)簽,同時(shí)不要嵌套過多的循環(huán)。
// 語(yǔ)法
label: statement
with 語(yǔ)句
- with 語(yǔ)句的作用是將代碼的作用域設(shè)置到一個(gè)特定的對(duì)象中。
- 主要目的:簡(jiǎn)化多次編寫同一個(gè)對(duì)象的工作。
// 語(yǔ)法
with (expression) statement;
// 示例:
// 把變量都包含在 location 對(duì)象中。
with(location) {
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
??
大量使用with語(yǔ)句會(huì)導(dǎo)致性能下降,同時(shí)也會(huì)給調(diào)試代碼造成困難,因此在開發(fā)大型應(yīng)用程序時(shí),不建議使用with語(yǔ)句。
函數(shù)
通過函數(shù)可以封裝任意多條語(yǔ)句,而且可以在任何地方、任何時(shí)候調(diào)用執(zhí)行。
ECMAScript 中的函數(shù)在定義時(shí)不必指定是否返回值。
// 定義
// 關(guān)鍵字 函數(shù)名(參數(shù))
function functionName(arg0, arg1,...argN) {
statments
}
// 函數(shù)聲明
function sayHi(num1, num2) {
alert("Hello " + arguments[0] + "," + arguments[1]); // 用類似數(shù)組的方式訪問傳入的參數(shù)
alert(arguments.length); // 傳入?yún)?shù)的個(gè)數(shù)
if(arguments.length == 1) {
alert(arguments[0] + 10);
}else if {
alert(arguments[0] + num2);
}
}
// 函數(shù)體內(nèi)通過 arguments 對(duì)象訪問參數(shù)數(shù)組。
// arguments 與 命名參數(shù)的內(nèi)存空間是相互獨(dú)立的;
// ***特性:?jiǎn)蜗蛴绊?**:修改 arguments 的值會(huì)自動(dòng)映射同步到命名參數(shù)上,反之則不能;
// arguments 對(duì)象的長(zhǎng)度由傳入的參數(shù)個(gè)數(shù)決定;
參數(shù)
- ECMAScript 函數(shù)的重要特點(diǎn):命名的參數(shù)只是提供便利,但不是必須的。
- ECMAScript 函數(shù)中的參數(shù)在內(nèi)部是用一個(gè)數(shù)組來(lái)表示的。在函數(shù)體內(nèi)可以通過
arguments對(duì)象來(lái)訪問這個(gè)參數(shù)數(shù)組,從而獲取傳遞給函數(shù)的每一個(gè)參數(shù)。 -
arguments對(duì)象的長(zhǎng)度是由傳入的參數(shù)個(gè)數(shù)決定的,不是由定義函數(shù)時(shí)的命名參數(shù)的個(gè)數(shù)決定的。 -
arguments對(duì)象可以與命名參數(shù)一起使用。而且arguments對(duì)象的值永遠(yuǎn)與對(duì)應(yīng)命名參數(shù)的值保持同步,但它們的內(nèi)存空間是獨(dú)立的。 - 沒有傳遞值的命名參數(shù)將自動(dòng)被賦予
undefined值。 - 由于不存在函數(shù)簽名的特性,ECMAScript 函數(shù)不能重載。(就是函數(shù)名相同、參數(shù)的個(gè)數(shù)不同的函數(shù))。
- 無(wú)須指定函數(shù)的返回值,因?yàn)槿魏?ECMAScript 函數(shù)都可以在任何時(shí)候返回任何值。實(shí)際上,未指定返回值的函數(shù)返回的是一個(gè)特殊的
undefined值。 - 函數(shù)中
arguments.length屬性可以返回傳入?yún)?shù)的個(gè)數(shù),實(shí)際上,函數(shù)的。length屬性與實(shí)際傳入的參數(shù)個(gè)數(shù)無(wú)關(guān),只反映函數(shù)預(yù)期傳入的參數(shù)個(gè)數(shù) -
嚴(yán)格模式對(duì)如何使用
arguments對(duì)象做出了一些限制。首先,在函數(shù)體內(nèi)直接對(duì)arguments對(duì)象中的元素賦值是無(wú)效的。也就是說,即使把 arguments[1] 設(shè)置為 10,該函數(shù)的參數(shù)值仍然還是undefined。其次,重寫arguments的值會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤(代碼將不會(huì)執(zhí)行)。
function howManyArgs () {
console.log(arguments.length);
}
howManyArgs("string", 45); //2
howManyArgs(); //0
howManyArgs(12); //1
函數(shù)的傳值
函數(shù)參數(shù)如果是原始類型的值(數(shù)值、字符串、布爾值),傳遞方式是傳值傳遞(passes by value)。這意味著,在函數(shù)體內(nèi)修改參數(shù)值,不會(huì)影響到函數(shù)外部。
如果函數(shù)參數(shù)是復(fù)合類型的值(數(shù)組、對(duì)象、其他函數(shù)),傳遞方式是傳址傳遞(pass by reference)。也就是說,傳入函數(shù)的原始值的地址,因此在函數(shù)內(nèi)部修改參數(shù),將會(huì)影響到原始值。
函數(shù)的作用域
函數(shù)執(zhí)行時(shí)所在的作用域,是定義時(shí)的作用域,而不是調(diào)用時(shí)所在的作用域。
var a = 1;
// 函數(shù) x 的作用域綁定在外層
var x = function () {
console.log(a);
};
function f() {
var a = 2;
x(); // x 函數(shù)執(zhí)行時(shí),所處的是定義時(shí)的作用域。
}
f() // 1
立即調(diào)用的函數(shù)表達(dá)式(IIFE)
在定義函數(shù)之后,立即調(diào)用該函數(shù):
(function(){ /* code */ }());