為了鞏固JavaScript基礎知識,重讀了《JavaScript高階程式設計》一書,歸納總結了一些在平常程式設計中比較少用到的知識點(尤其是瀏覽器端程式設計),第一部分主要總結前五章的內容,包括基本概念、變數、作用域、記憶體及引用型別相關的問題。
1. 基本概念
1. <script>
標籤的asnyc
與defer
這是async
與defer
在頁面渲染時的時序圖,藍色線代表網路讀取,紅色線代表執行時間,這倆都是針對指令碼的;綠色線代表HTML
解析。
也就是說async
是亂序的,而defer
是順序執行,這也就決定了async
比較適用於百度分析或者谷歌分析這類不依賴其他指令碼的庫。從圖中可以看到一個普通的<script>
標籤的載入和解析都是同步的,會阻塞DOM
的渲染,這也就是我們經常會把<script>
寫在<body>
底部的原因之一,為了防止載入資源而導致的長時間的白屏,另一個原因是js可能會進行DOM
操作,所以要在DOM
全部渲染完後再執行。
2. 所有資料型別的值都有與true
和false
等價的值
資料型別 | 轉換為true的值 | 轉換為false的值 |
---|---|---|
Boolean | true | true |
String | 任何非空字串 | 空字串 |
Number | 任何非零數字值(包括無窮大) | 0和NaN |
Object | 任何物件 | null |
Undefined | n/a | undefined |
初始化變數時應賦予這裡的轉換為false
的值,如初始化一個物件,則使用var obj = null
,這樣方便判斷變數為空的狀況,有利於對JavaScript
這種弱型別語言的型別管理。
3. 數字的無窮值Infinity
js
中的最大數字儲存在Number.MAX_VALUE
中,最小數值儲存在Number.MIN_VALUE
中,Infinity
不能參與計算,使用isFinite()
方法判斷數字是否為無窮。
4. 關係操作符<
、>
、>=
、<=
判斷字串
判斷字串的大小,取決於第一個字元的字元編號,這可以應用到英文字母的位置判斷上(必須統一轉為大寫或小寫,可應用於按字母排序)
var result = 'Brick'.toLowerCase() > 'alphabet'.toLowerCase() // true
複製程式碼
判斷得到b
在字母表中的位置在a
的後面
5. for-in
迴圈
ECMAScript
的物件屬性沒有順序,因此,通過for-in
迴圈輸出的屬性名順序理論上是不可預測的,返回的先後次序可能會因瀏覽器而異。
6. for
迴圈的label
用於給for
迴圈做標記,使其可以對指定的迴圈進行break
或continue
操作
var a = 1;
label : for ( var i = 0; i < 5; i++ ) {
for ( var j = 0; j < 5; j++ ) {
if ( i == 3 ) {
break label;
}
a++;
}
}
console.log( a ); // 16
// 此時break跳出了指定的外部迴圈,整個迴圈巢狀結束,因此只執行了三次內部迴圈,+5+5+5結果為16
var a = 1;
for ( var i = 0; i < 5; i++ ) {
for ( var j = 0; j < 5; j++ ) {
if ( i == 3 ) {
break;
}
a++;
}
}
console.log( a ); // 21
// 此時沒有指定label,break跳出的是內部迴圈,即跳過了一次當i=3時的外部迴圈,因此總共執行了5-1=4次內部迴圈,+5+5+5+5結果為21
複製程式碼
7. switch
switch
語句在比較值時使用的是全等操作符,因此不會發生型別轉換。
8. 函式
- 在函式內部可以通過
arguments[0]
,arguments[1]
來訪問函式的引數,arguments
是一個類陣列物件(不是Array
的例項) - 使用
arguments.length
判斷引數長度常用於方法封裝,如:
function doSth () {
if (arguments.length === 1) {
alert(arguments[0])
} else if (arguments.length === 2) {
alert(arguments[0], arguments[1])
}
}
複製程式碼
換一種說法:通過檢查傳入函式中的引數型別和數量並做出不同的反應,可以模擬方法的過載(Java等語言中可以為函式編寫兩個定義,只要這兩個定義的簽名——接受的引數的型別和數量不同即可,這種函式呼叫的方式稱為函式過載)。
2. 變數、作用域、記憶體
1. 變數賦值
變數賦值中的引數傳遞只有按值傳遞,引用型別賦值時傳遞的是記憶體指標,由記憶體指標指向記憶體棧中的值,仍然是按值傳遞,參考下面例子:
function setName (obj) {
obj.name = 'Nicholas'
obj = new Object()
obj.name = 'Greg'
}
var person = new Object()
setName(person)
alert(person.name) // Nicholas
複製程式碼
由於在函式內對引數obj
建立了新物件,obj
擁有了新的記憶體地址(這是函式塊中的區域性變數),因此後面對物件的修改是針對新的記憶體地址中儲存的物件做的,所以原來傳進來的引數obj
所指向的物件不會被修改,因此obj.name
會返回未宣告新記憶體指標時賦值的結果Nicholas
。
2. 函式引數的作用域
函式的引數被當做變數來對待,因此其訪問規則與執行環境中的其他變數相同(函式引數相當於函式內的區域性變數)。
3. 垃圾回收策略
- 標記清除
先將記憶體中所有變數進行標記;然後清除作用域
中的變數以及被作用域
中變數引用的變數的標記;把剩下的標記視為待清除的變數;執行清除——銷燬標記並回收記憶體。
- 引用計數
引用計數通過跟蹤每個變數被引用的次數,等待某個變數的引用次數為0了,再執行清除。這會導致迴圈引用
的問題:
function problem () {
var objA = new Object()
var objB = new Object()
objA.someOtherObject = objB
objB.anotherObject = objA
}
複製程式碼
這裡objA
與objB
通過自身的屬性相互引用,其引用次數始終為2,因此在引用計數的策略下這兩個變數的記憶體始終得不到回收,導致效能下降甚至崩潰。
在IE9以下的IE版本中,BOM物件和DOM物件並不是原生的JavaScript物件,而是用C++通過COM物件(Component Model Object元件模型物件)的形式實現的,而COM就是使用引用計數進行垃圾清除的,因此在這些版本中,若發生DOM或BOM物件與原生JavaScript物件互相引用的情況,也會出現迴圈引用的問題:
var element = document.getElementById('some_element')
var myObject = new Object()
myObject.element = element
element.someObject = myObject
複製程式碼
上例中,一個DOM元素與一個原生JavaScript物件產生了迴圈引用,此時就算DOM節點從html上移除,DOM物件也會一直存在與記憶體中
- 效能問題
IE的垃圾回收頻率是通過記憶體分配量來界定的,當記憶體佔用超過某個臨界值就會觸發回收,IE7之前,這個臨界值是固定的(256個變數、4096個物件字面量和陣列元素或者64kb的字串),但是如果一個程式擁有這麼多變數,那他變數的記憶體佔比一定會長期保持在這樣的高水平,因此會不斷觸發垃圾回收,導致效能爆炸。IE7對此進行了優化,根據記憶體佔比動態設定臨界值。
- 解除引用
全域性變數在使用後應儘量通過手動方式解除引用,避免無謂佔用記憶體。
// 解除引用
var asd = { a: 213 }
asd = null
複製程式碼
執行解除引用語句並不是馬上將變數佔用的記憶體釋放,而是將其加入標記,以便下一次垃圾回收操作執行時將其回收。
3. 引用型別
1. 物件字面量
宣告物件一般有兩種方式,一是通過new
操作符建立Object
建構函式的例項,二是通過物件字面量語法進行建立
// new
var obj1 = new Object()
// 物件字面量
var obj2 = {}
複製程式碼
- 在運用物件字面量建立物件時,實際上不會呼叫
Object
建構函式- 一般來講,在封裝函式時,雖然命名引數容易處理,但在處理大量資料時則會顯得不夠靈活,因此一般對必須傳入的引數用命名引數處理,而大量的可選引數則使用物件字面量傳入。
2. 陣列操作符
arr.push()
:入棧。可以同時推入多個值,如arr.push(1, 2, 3)
,則會依次在陣列最後追加1、2、3三個值。arr.pop()
:出棧。對陣列最後一個值執行出棧操作,並返回這個值,出棧操作會修改原陣列。arr.unshift()
:進入佇列。在陣列最前推入值,同樣可以推入多個值:arr.unshift(1, 2, 3)
。arr.shift()
:退出佇列。將陣列第一項退出佇列,並返回這個值,退出佇列操作會修改原陣列。arr.reverse()
:反轉。單純用於反轉陣列順序,如[1, 3, 2, 5, 4].reverse()
會得到[4, 5, 2, 3, 1]
arr.sort()
:排序。預設情況下,sort()
對陣列進行升序排序,這種升序排序是呼叫每個陣列項的toString()
方法轉型再進行比較,即使所有陣列項都是數字,因此一般在sort()
中傳入比較函式去實現正確的排序
比較函式接收兩個引數,如果第一個引數應該位於第二個引數之前則返回一個負數,如果兩個引數相等則返回0,如果第一個引數應該位於第二個引數之後則返回一個正數。
// 這個比較函式適用於大多數資料型別,呼叫時將整個函式作為引數傳入到sort()中即可
function compare (val1, val2) {
if (val1 < val2) {
return -1
} else if (val1 > val2) {
return 1
} else {
return 0
}
}
var arr = [1, 3, 2, 5, 4]
arr.sort(compare) // [1, 2, 3, 4, 5]
// 對於數值型別或呼叫其valueOf()方法會返回數值的變數型別,可以使用這個更簡單的函式
function compareEasy (val1, val2) {
return val2 - val1
}
複製程式碼
arr1.concat()
:拼接。先建立一個陣列的副本,再將引數拼接到這個副本後面
// 若沒有接收到引數,則返回該副本,此方法可用於進行陣列深複製
var copy = [1, 2, 3].concat() // [1, 2, 3]
// 若接收到的引數是一個或多個陣列,則將陣列所有項新增到結果陣列最後
var arr1 = [1, 2, 3].concat([4, 5], [6]) // [1, 2, 3, 4, 5, 6]
// 若接收到的引數不是陣列,這些值則會被簡單的新增到結果陣列後面
var arr2 = [1, 2, 3].concat(4, 5) // [1, 2, 3, 4, 5]
複製程式碼
arr.split()
:基於陣列中的一個或多個項建立新陣列
// 傳入一個引數,返回包含這個位置到陣列末尾內容的新陣列
var arr1 = [1, 2, 3, 4, 5].slice(1) // [2, 3, 4, 5]
// 傳入兩個引數,返回包含開始位置到不包含結束位置內容的新陣列
var arr2 = [1, 2, 3, 4, 5].slice(1, 4) // [2, 3, 4]
// 傳入引數為負數,則將開始與結束位置從陣列最後一項開始計算,返回新陣列
var arr3 = [1, 2, 3, 4, 5].slice(-2, -1) // [4]
// 如果結束位置小於起始位置,則返回空陣列
var arr4 = [1, 2, 3, 4, 5].slice(-1, -2) // []
複製程式碼
arr.splice()
:提供陣列的插入、刪除和替換功能,呼叫這個函式時始終會返回一個陣列,包含了從原始陣列中刪除的項(若沒有刪除則返回空陣列)
// 刪除:指定要刪除第一項的位置與要刪除的項數
var arr1 = [1, 2, 3, 4, 5].splice(0, 2) // 返回:[1, 2],原陣列:[3, 4, 5]
// 插入:指定要插入項的位置,0(刪除項數)和要插入的項
var arr2 = [1, 2, 3, 4, 5].splice(2, 0, 'a', 'b') // 返回:[],原陣列:[1, 2, 'a', 'b', 3, 4, 5]
// 替換:指定要插入項的位置,刪除項數和要插入的項
var arr2 = [1, 2, 3, 4, 5].splice(2, 1, 'a', 'b') // 返回:[3],原陣列:[1, 2, 'a', 'b', 4, 5]
複製程式碼
arr.indexOf() & arr.lastIndexOf()
:用於查詢某個項在陣列中的位置,區別是indexOf()
從陣列開頭開始查詢,lastIndexOf()
從陣列末尾開始查詢,它們都包含兩個引數,一是要查詢的項,二是查詢起點的位置,它在查詢比較的時候使用全等操作符,因此必須保證查詢項與目標的資料型別一致
var arr = [1, 2, 3, 2, 1]
arr.indexOf(0) // -1
arr.indexOf(1) // 0
arr.lastIndexOf(1) // 4
arr.indexOf(1, 2) // 4
// 它在查詢引用型別變數時是通過引用進行對比
var obj = { attr: 1 }
var arr1 = [{ attr: 1 }]
var arr2 = [obj]
arr1.indexOf(obj) // -1
arr2.indexOf(obj) // 0
複製程式碼
arr.every() & arr.filter() & arr.forEach() & arr.map() & arr.some()
:迭代。每個方法都接收兩個引數:要在每一項上執行的函式和執行該函式的作用域物件——影響this的值。傳入這些方法中的函式會接收三個引數:陣列項的值、該項在陣列中的位置和陣列本身。
every()
:對陣列中的每一項執行給定函式,如果該函式對每一項都返回true
,則返回true
。
filter()
:對陣列中每一項執行給定函式,返回該函式會返回true
的項組成的陣列。
forEach()
:對陣列中每一項執行給定函式,沒有返回值。
map()
:對陣列中每一項執行給定函式,返回每次函式呼叫呼叫的結果組成的陣列。
some()
:對陣列中的每一項執行給定函式,如果該函式對任一項返回true
,則返回true
arr.reduce() & arr.reduceRight()
:歸併。迭代所有陣列項,構建一個返回值,它們都接收兩個引數,一個在每一項上呼叫的函式和作為歸併基礎的初始值(可選),傳入的函式接收4個引數:前一個值、當前值、項的索引和陣列物件。
// 對所有陣列項求和
var values = [1, 2, 3, 4, 5]
var sum = values.reduce(function (prev, cur, index, array) {
return prev + cur
}) // 15
複製程式碼
3. Date
物件
Date.parse()
:可以用於將固定的日期格式字串轉換為時間戳,支援下列日期格式
月/日/年:
6/13/2018
英文月名 日,年:January 12,2018
英文星期幾 英文月名 日 年 時:分:秒 時區:Tue May 25 2018 00:00:00 GMT-0700
ISO8601
擴充套件格式YYYY-MM-DDTHH:mm:ss:sssZ
:2018-05-25T00:00:00
Date.now()
:用於更便捷地獲取當前系統時間戳Date
型別的例項可以直接用大於小於號進行比較,它會呼叫其valueOf()
方法將日期物件轉換為時間戳,再進行數值間的比較。
4. RegExp
物件
- 使用字面量方式建立正則:
var expression = / pattern / flags
。每個正則都會有一個或多個標識(flags
),標明正規表示式的行為。
g
:表示全域性(global
)模式,意味著正則會匹配所有的字元,而不是匹配到第一個字元就終止。
i
:表示不區分大小寫(case-insensitive
)模式,在匹配時不區分大小寫。
m
:表示多行(multiline
)模式,即在到達一行文字末尾時還會繼續查詢下一行中是否存在匹配正則的項。
RegExp
屬性↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
global
:布林值,表示是否設定了g
標識ignoreCase
:布林值,表示是否設定了i
標識multiline
:布林值,表示是否設定了m
標識lastIndex
:整數,表示上一次匹配成功位置的下一個位置,下一次搜尋從這個位置開始source
:正規表示式的字串表示,按照字面量形式而非傳入建構函式的字串模式返回
RegExp
方法↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
exec()
:它接收一個引數,用於匹配正則的字串,返回包含第一個匹配項資訊的陣列。同一個正則連續進行exec()會匹配到下一個滿足規則的位置(區別於只能返回第一個匹配位置的test()
)
var text = 'cat, bat, sat, fat'
var pattern = /.at/g
var matches = pattern.exec(text)
console.log(matches.index) // 0
console.log(matches[0]) // cat
console.log(matches.lastIndex) // 3
matches = pattern.exec(text)
console.log(matches.index) // 5
console.log(matches[0]) // bat
console.log(matches.lastIndex) // 8
複製程式碼
RegExp
原型屬性:這些屬性基於最近執行的一次正規表示式生成
長屬性名 | 短屬性名 | 說明 |
---|---|---|
input |
$_ | 最近一次要匹配的字串。Opera未實現該屬性 |
lastMatch |
$& | 最近一次的匹配到的內容。Opera未實現該屬性 |
lastParen |
$+ | 最近一次匹配的捕獲組。Opera未實現該屬性 |
leftContext |
$` | input字串中lastMatch之前的文字 |
multiline |
$* | 布林值,表示是否所有正則都使用多行模式。IE和Opera未實現該屬性 |
rightContext |
$' | input字串中lastMatch之後的文字 |
var text = 'this has been a short summer'
var pattern = /(.)hort/g
if (pattern.test(text)) {
console.log(RegExp.input) // this has been a short summer
console.log(RegExp.leftContext) // this has been a
console.log(RegExp.rightContext) // summer
console.log(RegExp.lastMatch) // short
console.log(RegExp.lastParen) // s
console.log(RegExp.multiline) // false
}
複製程式碼
RegExp
還提供了RegExp.$1
等九個用於儲存第一到第九個捕獲組,在呼叫exec()
或test()
時這些捕獲組就會自動填充。
var text = 'this has been a short summer'
var pattern = /(..)or(.)/g
if (pattern.test(text)) {
alert(RegExp.$1)
alert(RegExp.$2)
}
複製程式碼
5. Function
型別
arguments.callee
:用於在函式內部獲取使用這個引數函式本身:
// 階乘,一般使用遞迴實現,但這個方法卻會與函式名耦合
function factorial (num) {
if (num <= 1) {
return 1
} else {
return num * factorial(num - 1)
}
}
// 使用arguments.callee解耦
function factorial (num) {
if (num <= 1) {
return 1
} else {
return num * arguments.callee(num - 1)
}
}
複製程式碼
arguments.callee.caller
:使用函式的caller
屬性可以訪問呼叫這個函式的環境,在函式內部可以通過arguments.callee.caller
訪問,ES5
還定義了值為undefined
的arguments.caller
欄位與函式本身的caller
欄位進行區分。而在嚴格模式下,訪問arguments.callee
和arguments.caller
都會導致錯誤。length & prototype
:分別儲存函式希望接收引數的個數和函式的原型物件。
ES6中length只會返回沒有指定預設值的引數個數
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
複製程式碼
call() & apply()
:可以改變函式的作用域來進行呼叫,區別是call()
方法的傳參是將引數用逗號連線,apply()
方法的傳參是將引數包含在一個陣列中:
function sum (num1, num2) {
return num1 + num2
}
function callSum1 (num1, num2) {
return sum.apply(this, arguments)
}
function callSum2 (num1, num2) {
return sum.apply(this, [num1, num2])
}
function callSum3 (num1, num2) {
return sum.call(this, num1, num2)
}
console.log(callSum1(10, 10)) // 20
console.log(callSum2(10, 10)) // 20
console.log(callSum3(10, 10)) // 20
複製程式碼
上面apply()
與call()
呼叫時第一個傳入的引數this
指的就是呼叫時所要指向的作用域:
window.color = 'red'
var o = { color: 'blue' }
function sayColor () { alert(this.color) }
sayColor() // red:呼叫環境為全域性作用域,因此得到window.color
sayColor.call(this) // red:傳入this指定為全域性作用域,得到window.color
sayColor.call(window) // red:作用域直接指定為window,得到window.color
sayColor.call(o) // blue:作用域指定為o,得到o.color
複製程式碼
擴充ES6宣告方式的結果解析
// 箭頭函式在定義時已經確定this的指向;箭頭函式沒有自己的this,它始終引用外層函式的this
window.color = 'red'
var o = {
color: 'blue',
sayColor: () => { alert(this.color) }
}
o.sayColor() // red:箭頭函式中this指向宣告時外層函式的this,此處外層只有全域性作用域,因此取window.color
o.sayColor.call(this) // red:指定了全域性作用域,取window.color
o.sayColor.call(window) // red:指定了全域性作用域,取window.color
o.sayColor.call(o) // red:箭頭函式中this指向宣告時外層函式的this,此處外層只有全域性作用域,因此取window.color
複製程式碼
// 等同於sayColor: function () { alert(this.color) }
window.color = 'red'
var o = {
color: 'blue',
sayColor () { alert(this.color) }
}
o.sayColor() // blue:從o中呼叫時預設使用o為當前作用域,取o.color
o.sayColor.call(this) // red:指定了全域性作用域,取window.color
o.sayColor.call(window) // red:指定了全域性作用域,取window.color
o.sayColor.call(o) // blue:指定了o為作用域,取o.color
複製程式碼
bind()
:也可以用來改變函式作用域,但是這個方法返回一個改變作用域後的函式宣告,需要再接上一對圓括號才會執行
window.color = 'red'
var o = { color: 'blue' }
function sayColor () { alert(this.color) }
sayColor.bind(o)() // blue
複製程式碼
6. 基本包裝型別Boolean
、String
、Number
- 事實上,訪問一個基礎型別值的方法或屬性時,
js
引擎會進入一種“讀取模式”,它會建立基礎型別的例項物件,再呼叫例項物件中的屬性或方法,再把這個例項物件登出:
// 執行這些程式碼時
var s1 = 'abc'
var s2 = s1.substring(s1)
// 事實上引擎是這樣操作的
var s1 = new String('abc')
var s2 = s1.substring(s1)
s1 = null
複製程式碼
使用new
操作符建立的物件例項與基本包裝型別區別在於其宣告週期,物件例項在執行流離開當前作用域之前會一直存在(就像一個引用型別變數),而基本包裝型別則只在一行程式碼訪問它的時候建立,離開這行程式碼就會立即銷燬:
var s1 = 'abc'
s1.color = 'blue'
console.log(s1.color) // undefined
複製程式碼
Number
型別方法↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
toExponential()
:返回數字的科學計數法表示,它接收一個,參數列示保留到小數點後的位數
var num = 10
console.log(num.toExponential(1)) // '1.0e+1'
複製程式碼
toPrecision()
:返回數字最合理的表示方式,可能是科學計數法也可能是數值,它接收一個引數,表示所有數值的位數
var num = 99
console.log(num.toPrecision(1)) // '1e+2':在需要捨棄末尾數時進行四捨五入
console.log(num.toPrecision(2)) // '99'
console.log(num.toPrecision(3)) // '99.0'
複製程式碼
String
型別方法↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
-
concat()
:連線字串 -
slice() & substr() & substring()
:這三個方法會基於被操作字串返回一個子字串,它們接收一或兩個引數:第一個指向操作的開始位置,第二個指向操作的結束位置(其中slice()
和substring()
的二引數指操作最後一個字元的位置,substr()
的二引數指操作的字元個數)
var str = 'hello world'
str.slice(3) // 'lo world'
str.substring(3) // 'lo world'
str.substr(3) // 'lo world'
str.slice(3, 7) // 'lo w'
str.substring(3, 7) // 'lo w'
str.substr(3, 7) // 'lo worl'
// 傳入負數時,三個方法的處理方式則不同:slice()將負數與字串長度相加;substr()將第一個引數與字串長度相加、第二個引數轉換為0;substring()會將所有負值引數轉換為0
var str = 'hello world'
str.slice(-3) // 'rld'
str.substring(-3) // 'hello world'
str.substr(-3) // 'rld'
str.slice(3, -4) // 'lo w'
str.substring(3, -4) // 'hel'
str.substr(3, -4) // ''
複製程式碼
indexOf() & lastIndexOf()
:傳入兩個引數,要匹配的字串和開始匹配的位置,返回第一個匹配到的內容的位置trim()
:刪除字串前置與字尾的所有空格toUpperCase() & toLocaleUpperCase() & toLowerCase() & toLocaleLowerCase()
:字元全部替換為大/小寫,Locale針對不同語言環境做了特定的實現,一般在不知道語言環境的情況下用Locale系列比較穩妥match() & search()
: 共同點:都接收一個引數,返回匹配到第一個字串的值 不同點:search()只能接收正則,match()可以接收字串或正則;search()只能從字串開頭查詢匹配的第一個位置(會忽略g的全域性標識),match()若沒有設定g標識,表現與search()一樣,若設定了g標識,則會進行全域性檢索,返回由捕獲組組成的陣列(與RegExp物件的exec()方法返回結果一樣)
var text = 'cat, bat, sat, fat'
var pattern = /.at/
var matches = text.match(pattern)
console.log(matches.index) // 0
console.log(matches[0]) // 'cat'
console.log(pattern.lastIndex) // 0
var pos = text.search(/at/)
console.log(pos) // 1
複製程式碼
replace()
:它接收兩個引數,一是一個字串或一個正則,指定要被替換的內容;二是一個字串,指定要替換進去的內容。如果要對所有匹配到的字元進行替換,則必須在第一個引數傳入正則並帶上引數
var text = 'cat, bat, sat, fat'
var result = text.replace('at', 'ond') // 'cond, bat, sat, fat'
result = text.replace(/at/g, 'ond') // 'cond, bond, sond, fond'
複製程式碼
在第二個引數中還可以使用一些特殊的字元序列來把正則匹配到的值插入到結果字串中
字元序列 | 替換文字 |
---|---|
$$ | $ |
$& | 匹配整個模式的子字串,與RegExp.lastMatch的值相同 |
$' | 匹配的子字串之後的子字串,與RegExp.leftContext的值相同 |
$` | 匹配的子字串之前的子字串,與RegExp.rightContext的值相同 |
$n | 匹配第n個捕獲組的子字串,,從1~9,如$1 |
$nn | 匹配第nn個捕獲組的子字串,從01-99,如$01 |
var text = 'cat, bat, sat, fat'
var result = text.replace(/(.at)/g, 'word($1)') // 'word(cat), word(bat), word(sat), word(fat)'
result = text.replace(/(.at)/g, 'word($&)') // 'word(cat), word(bat), word(sat), word(fat)'
result = text.replace(/(.at)/g, 'word($\')') // 'word(, bat, sat, fat), word(, sat, fat), word(, fat), word()'
result = text.replace(/(.at)/g, 'word($\`)') // 'word(), word(cat, ), word(cat, bat, ), word(cat, bat, sat, )'
複製程式碼
第二個引數還可以傳入一個函式,通過return
指定要替換進去的值。在只有一個匹配項的時候,會向函式傳遞三個引數:模式的匹配項、模式匹配項在字串中的位置和原始字串
function htmlEscape (text) {
return text.replace(/[<>"&]/g, function (match, pos, originalText) {
switch (match) {
case '<': return '<'
case '>': return '>'
case '"': return '"'
case '&': return '&'
}
})
}
alert(htmlEscape('<p class="greeting">Hello world</p>')) // <p class="greeting">Hello world</p>
複製程式碼
split()
:用於將字串按照指定的分隔符切割成多段,並將結果放在一個陣列中,它接收兩個引數:一是一個正則或一個字串,用於指定分隔符;二是一個數字,用於限定結果陣列的長度
var text = 'cat,bat,sat,fat'
text.split(',') // ['cat', 'bat', 'sat', 'fat']
text.split(',', 2) // ['cat', 'bat']
text.split(/[^\,]+/) // ['', ',', ',', ',', '']
複製程式碼
localeCompare()
:用於比較主體與引數字串在字母表中的先後順序,返回結果與地區語言有關fromCharCode()
:靜態方法,將字元編號轉化為字元,本質上是與例項方法charCodeAt()執行相反的操作
String.fromCharCode(104, 101, 108, 108, 111) // hello
複製程式碼