国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript易錯(cuò)知識(shí)小點(diǎn)

rottengeek / 1651人閱讀

摘要:字符串在字符串中找到匹配的字面量,只能替換一次出現(xiàn)的匹配項(xiàng),暫不存在函數(shù),想要替換多次出現(xiàn)的匹配項(xiàng),必須使用正則表達(dá)式標(biāo)識(shí)。這符合賦值改變但不破壞繼承屬性的理念。二十七數(shù)組構(gòu)造函數(shù)判斷是否為一個(gè)數(shù)組,能夠正確處理跨域?qū)ο蟆?/p>

一、String, Number, Boolean等包裝類型是對(duì)象,JavaScript沒(méi)有比較對(duì)象的方法,即使通過(guò)寬松比較相等==
var a = new String("abc");
var b = new String("abc");
console.log(a == b) // false
console.log(a === b) // false
二、對(duì)包裝類型轉(zhuǎn)換為原始值只能正確提取出字符串和數(shù)字,而不布爾值不能
Boolean(new Boolean(false)) // true
Number(new Number(123)) // 123
String(new String("abc")) // abc

new Boolean(new Boolean(false)) // true對(duì)象
三、String.prototype.split(separator?, limit?)

作用: 通過(guò)指定邊界(separator)將字符串分割成子字符串,返回字符串組成的數(shù)組。

separator: 可選,可以為字符串或正則表達(dá)式。不傳的話,將原字符串封裝在數(shù)組中返回

limit: 可選, 若傳入,最多返回?cái)?shù)組中l(wèi)imit個(gè)子字符串

注:若separator為包含子表達(dá)式分組的正則表達(dá)式,子表達(dá)式匹配的字符串也會(huì)作為數(shù)組中的元素返回。

"a, b   ,   ".split(/(,)/)
# ["a", ",", " b   ", ",", "   "]
四、String.prototype.match(regexp)

作用: 捕獲分組或返回所有匹配的子字符串

注: 若regexp未設(shè)置全局標(biāo)志/g, 則返回一個(gè)對(duì)象(數(shù)組: 存在index和input屬性),存放第一次匹配相關(guān)的信息;若設(shè)置了/g標(biāo)志,則將所有匹配的子字符串(不包含分組元素)放在一個(gè)數(shù)組中返回; 如果未匹配到任何子字符串,返回null

var a = "-abb--aaab".match(/(a+)b/) // ["ab", "a"]
a.index === 1 // true
a.input === "-abb--aaab" // true
var b = "-abb--aaab".match(/(a+)b/g) // ["ab", "aaab"]
b.index === undefined // true
b.input === undefined // true
var c = "-abb--aaab".match(/(a+)bc/g) // null
c === null // true
五、String.prototype.replace(search, replacement)

存在兩個(gè)參數(shù): search, replacement

search: 字符串或者正則表達(dá)式。

1) 字符串: 在字符串中找到匹配的字面量,只能替換一次出現(xiàn)的匹配項(xiàng),暫不存在
    (replaceAll函數(shù)),想要替換多次出現(xiàn)的匹配項(xiàng),必須使用正則表達(dá)式/g標(biāo)識(shí)。
2) 正則表達(dá)式: 對(duì)輸入的字符串進(jìn)行匹配。如果想替換多次,必須使用/g標(biāo)識(shí)

replacement: 字符串或者函數(shù)。

1) 字符串: 描述如何替換找到的匹配項(xiàng)), 使用該字符串替換匹配項(xiàng),替換字符串中的$
符號(hào)允許使用完全匹配或者匹配分組進(jìn)行替換
2) 函數(shù): 執(zhí)行替換并提供參數(shù)匹配信息.

"iixxxixx".replace("i", "o") // oixxxixx
"iixxxixx".replace(/i/, "o") // oixxxixx
"iixxxixx".replace(/i/g, "o") // ooxxxoxx

// 使用$符號(hào)
"iixxxixx".replace(/i+/g, "($&)") // (ii)xxx(i)xx
"iixxxixx".replace(/(i+)/g, "($1)") // (ii)xxx(i)xx

// 使用函數(shù)替換
function repl(search, group, offset, input) {
    return "{ search: " + search.toUpperCase() + ", group: " + group + ", offset: " + offset + " }";
}
"iixxxixx".replace(/(i+)/g, repl)
// { search: II, group: ii, offset: 0 }xxx{ search: I, group: i, offset: 5 }xx
1. replacement為字符串

內(nèi)容用來(lái)逐字替換匹配項(xiàng),唯一例外是特殊字符美元符號(hào)($),它會(huì)啟動(dòng)替換指令

分組:$n在匹配中插入分組n。n必須大于等于1($0沒(méi)有任何特殊含義)

匹配的子字符串:

1) $` (反引號(hào))插入匹配項(xiàng)之前的文本
2) $& 插入完整的匹配項(xiàng)
3) $" (單引號(hào))插入匹配項(xiàng)之后的文本

$$ 插入單個(gè)$字符

"axb cxd".replace(/x/g, "($`,$&,$")"); // a(a,x,b cxd)b c(axb c,x,d)d
""foo" and "bar"".replace(/"(.*?)"/g, "#$1#"); // #foo# and #bar#
2. replacement為函數(shù)

如果replacement為函數(shù),它需要對(duì)替換匹配項(xiàng)的字符串進(jìn)行處理。簽名如下:

function replacement (search, group_1, ..., group_n, offset, input){}

search與前面介紹的$&(完整的匹配項(xiàng))相同, offset表示找到匹配項(xiàng)的位置,input是正在被匹配的字符串

search: 正則表達(dá)式匹配到的字符串

group: 如果存在分組,該值為匹配到的分組值, 可變參數(shù), 匹配到分組有多少個(gè),這個(gè)參數(shù)就有多少個(gè), 如果不存在,表示匹配到子字符所在原字符串的位置

offset(倒數(shù)第二個(gè)參數(shù)): 匹配到子字符所在原字符串的位置

input(最后一個(gè)參數(shù)): 原字符串

function replaceFunc (match) { return 2 * match; }
"3 peoples and 5 oranges".replace(/d+/g, replaceFunc); // 6 peoples and 10 oranges
六、檢查value是否為對(duì)象
function isObject (value) {
    return value === Object(value);
}
七、Array.prototype.forEach()的thisValue

forEach函數(shù)存在兩個(gè)參數(shù),第一個(gè)是回調(diào)函數(shù),第二個(gè)參數(shù)為第一個(gè)參數(shù)(回調(diào)函數(shù))提供this

var obj = {
    name: "Jane",
    friends: ["Tarzan", "Cheeta"],
    loop: function () {
        "use strict";
        this.friends.forEach(function (friend) {
            console.log(this.name + " knows " + friend);
        }, this)
    }
}
八、使用給定的prototype創(chuàng)建新對(duì)象

使用方法: Object.create(proto, properties?)

參數(shù):

proto: 新創(chuàng)建對(duì)象的原型

properties: 可選,通過(guò)描述符給新創(chuàng)建對(duì)象添加屬性

var PersonProto = {
    describe: function () {
        return "Person named " + this.name;
    }
}

var jane = Object.create(PersonProto, {
    name: { value: "Jane", writable: true, configurable: true, enumerable: true }
});

jane.describe() // "Person named Jane"
九、獲取對(duì)象的原型

調(diào)用方法: Object.getPrototypeOf(obj)

Object.getPrototypeOf(jane) === PersonProto // true
十、檢查一個(gè)對(duì)象是否是另外一個(gè)對(duì)象的原型

語(yǔ)法: Object.prototype.isPrototypeOf(obj)

檢查接受者是否是obj的原型(直接或者間接)

var A = {};
var B = Object.create(A);
var C = Object.create(B);
A.isPrototypeOf(C); // true

PersonProto.isPrototypeOf(jane); // true
十一、找到定義屬性的對(duì)象

遍歷對(duì)象obj的原型鏈, 返回鍵為propKey的自定義屬性的第一個(gè)對(duì)象

function getDefiningObject(obj, propKey) {
    while (obj && !Object.prototype.hasOwnProperty.call(obj, propKey)) {
        obj = Object.getPrototypeOf(obj);
    }

    return obj;
}
十二、列出自有的屬性鍵

可以列吃所有自有屬性,也可以列出可枚舉屬性

1) Object.getOwnPropertyNames(obj) 返回obj的所有自有屬性鍵
2) Object.key(obj) 返回obj所有可枚舉的自有屬性鍵
十三、通過(guò)屬性描述符獲取和設(shè)置屬性的特性

Object.defineProperty(obj, propKey, propDesc)
創(chuàng)建或改變obj對(duì)象的propKey鍵的屬性,并通過(guò)propDesc制定這個(gè)屬性的特性,返回修改后的對(duì)象

Object.getOwnPropertyDescriptor(obj, PropKey)
返回obj對(duì)象的propKey鍵自有(非繼承)屬性描述符,如果沒(méi)有該屬性,則返回undefined.

十四、復(fù)數(shù)對(duì)象

需求:

1) 就有相同的原型
2) 具有相同的屬性及屬性特性
function copyObject (orig) {
    // 1. copy has same prototype as orig
    var copy = Object.create(Object.getPrototypeOf(orig));

    // 2. copy ass orig"s own properties
    function copyOwnPropertiesFromObjct (target, source) {
        var ownProperties = Object.getOwnPropertyNames(source);
        for (var property of ownProperties) {
            var sourcePropertyDescriptor = Object.getOwnPropertyDescriptor(source, property);
            Object.defineProperty(target, property, sourcePropertyDescriptor);
        }
    }

    copyOwnPropertiesFromObjct(copy, orig);
    return copy;
}
十五、繼承的只讀屬性不能被賦值

如果一個(gè)對(duì)象obj從原型繼承了不可寫的屬性foo, 在嚴(yán)格模式下,那么不能給obj.foo賦值。

var proto = Object.create({}, { foo : { value: "a", writable: false } });
// var proto = Object.defineProperty({}, "foo", { value: "a", writable: false });
var obj = Object.create(proto);

obj.foo = "b"; // b
obj.foo // a

// IIFE
(function () { "use strict"; obj.foo = "b" }());
// Uncaught TypeError: Cannot assign to read only property "foo" of object "#"

這符合賦值改變但不破壞繼承屬性的理念。如果一個(gè)繼承屬性是只讀的,應(yīng)該禁止所有修改操作

十六、枚舉性影響下列操作
1) for-in // 循環(huán)所有可枚舉屬性(自有+繼承)
2) Object.keys() // 列出所有自有可枚舉屬性
2) JSON.stringify() // 所有自有可枚舉屬性
十七、保護(hù)對(duì)象之防止擴(kuò)展(Object.preventExtensions())

不能添加屬性,可以刪除屬性, 可以修改已有自有屬性

var obj = { foo: "a" };
Object.preventExtensions(obj);

obj.bar = "b"; // 寬松模式下,添加失敗
obj.bar // undefined

(function () { "use strict"; obj.bar = "b"  }()) // 嚴(yán)格模式下,拋出異常
// Uncaught TypeError: Can"t add property bar, object is not extensible

// 刪除屬性
delete obj.foo; // a
obj.foo // undefined

判斷某個(gè)對(duì)象是否可以擴(kuò)展: Object.isExtensible(obj)

Object.isExtensible(obj); // false
Object.isExtensible({}); // true

注: 防止擴(kuò)展時(shí),返回false

十八、保護(hù)對(duì)象之封閉(Object.seal())

不能添加屬性,且不能刪除屬性, 只能修改已有自有屬性。
(封閉 === 防止擴(kuò)展 + 不能刪除屬性)

var obj = { foo: "a" }

Object.getOwnPropertyDescriptor(obj, "foo"); // before sealing
// {value: "a", writable: true, enumerable: true, configurable: true}

Object.seal(obj);
Object.getOwnPropertyDescriptor(obj, "foo"); // after sealing
// {value: "a", writable: true, enumerable: true, configurable: false}

// 不能改變其屬性特性
Object.defineProperty(obj, "foo", { enumerable: false });
// Uncaught TypeError: Cannot redefine property: foo

判斷一個(gè)對(duì)象是否封閉: Object.isSealed(obj)

Object.isSealed(obj); // true
Object.isSealed({}); // false

注: 對(duì)象封閉時(shí),返回true

十九、保護(hù)對(duì)象之凍結(jié)(Object.freeze())

不能添加屬性,不能刪除屬性, 同時(shí)也修改已有自有屬性。
(凍結(jié) === 封閉 + 不能修改屬性)

var point = { x: 17, y: -5 };
Object.freeze(point);

// 賦值操作,寬松模式下,執(zhí)行失??;嚴(yán)格模式下,拋出異常。
point.x = 6
point.x // 17

(function () { "use strict"; point.x = 2; }());
// Uncaught TypeError: Cannot assign to read only property "x" of object "#"

(function () { "use strict"; point.z = 62; }());
// Uncaught TypeError: Can"t add property z, object is not extensible

(function () { "use strict"; delete point.x; }());
// Uncaught TypeError: Cannot delete property "x" of #

判斷一個(gè)對(duì)象是否被凍結(jié): Object.isFrozen(obj)

Object.isFrozen(obj); // true
Object.isFrozen({}); // false

注: 對(duì)象被凍結(jié)時(shí),返回true

二十、保護(hù)是淺層的

所有保護(hù)對(duì)象的方法,只能保護(hù)基本類型的自有屬性,對(duì)于對(duì)象不起作用(可以改變屬性值為對(duì)象中對(duì)象的屬性)

var obj = {
    foo: 1,
    bar: [1, 2, 3],
    cer: { a: "123" }
};
Object.freeze(obj);

obj.foo = 2; // no effect
obj.foo // 1

obj.bar.push("bar"); // 4: changes obj.bar
obj.bar // [1, 2, 3, "bar"]

obj.cer.b = "cer"; //cer: changes obj.cer
obj.cer // {a: "123", b: "cer"}
二十一、對(duì)象不是Object的實(shí)例

幾乎所有的對(duì)象都是Object的實(shí)例,因?yàn)镺bject.prototype在這些對(duì)象的原型鏈上,但也有對(duì)象不屬于這種情況。

Object.create(null) instanceof Object // false
Object.prototype instanceof Object // false

Object.getPrototypeOf(Object.create(null)) // null
Object.getPrototypeOf(Object.prototype) // null

這類對(duì)象位于原型鏈的末端,但typeof可以正確的把這些對(duì)象歸類為對(duì)象:

typeof Object.create(null) // object
typeof Object.prototype // object
二十二、跨域?qū)ο髾z測(cè)

在Web瀏覽器中,每一個(gè)幀和窗口都擁有自己的域,具有獨(dú)立的全局變量。這使得instanceof不可用于那些跨域的對(duì)象。

如果myvar是來(lái)自另一個(gè)域的數(shù)組,那么它的原型是那個(gè)域的Array.prototype。在當(dāng)前域中,使用instanceof檢測(cè)的是否為myvar的原型鏈上是否存在當(dāng)前域的Array.prototype, 會(huì)返回false。

可以使用ECMAScript 5的函數(shù)Array.isArray()來(lái)判斷是否為數(shù)組




  Test

  

  

二十三、備忘錄: 對(duì)象的使用 1. 對(duì)象字面量
var jane = {
    name: "Jane",
    "not an indentifier": 123,
    describe: function () {
        return "Person named " + this.name;
    }
}

jane.describe() // Person named Jane
2. 點(diǎn)操作符(.):通過(guò)固定鍵值訪問(wèn)屬性
obj.propKey // 訪問(wèn)
obj.propKey = value // 賦值
delete obj.propKey // 刪除
3. 中括號(hào)操作符([]): 通過(guò)計(jì)算出的鍵值訪問(wèn)屬性
obj["propKey"] // 訪問(wèn)
obj["propKey"] = value // 賦值
delete obj["propKey"] // 刪除
4.獲取和設(shè)置原型
Object.create(proto, propDescObj?) // 創(chuàng)建指定原型的對(duì)象
Object.getPrototypeOf(obj) // 獲取原型
5.屬性的遍歷和檢測(cè)
Object.keys(obj)

Object.getOwnPropertyNames(obj)

for (var propKey in obj)
Object.prototype.hasOwnProperty.call(obj, propkey)
6. 通過(guò)描述符獲取和定義屬性特性
// 定義
Object.defineProperty(obj, propKey, propDesc)
Object.defineProperties(obj, propDescObj)
Object.create(obj, propDescObj)

// 獲取
Object.getOwnPropertyDescriptor(obj, propKey)
7. 保護(hù)對(duì)象: 防止擴(kuò)展、封閉、凍結(jié)
// 防止擴(kuò)展: 不能添加屬性,能刪除屬性或修改屬性值
Object.preventExtensions(obj)
Object.isExtensible(obj)

// 封裝: 不能添加或者刪除屬性,能修改屬性值
Object.seal(obj)
Object.isSealled(obj)

// 凍結(jié): 不能添加或者刪除屬性,也不能修改屬性值
Object.freeze(obj)
Object.isFrozen(obj)
8. 所有對(duì)象的方法
// 將對(duì)象轉(zhuǎn)換為基本類型的值
Object.prototype.toString()
Object.prototype.valueOf()

// 返回本地語(yǔ)言環(huán)境的代表對(duì)象的字符串
Object.prototype.toLocalString()

// 原型式繼承和屬性
Object.prototype.isPrototypeOf(subObj)
Object.prototype.hasOwnProperty(propKey)
Object.prototype.propertyIsEnumerable(propKey)
二十四、通過(guò)字面量創(chuàng)建數(shù)組時(shí),最后的逗號(hào)會(huì)被忽略
["a", "b"].length // 2

["a", "b",].length // 2

["a", "b", ,].length // 3
二十五、空缺數(shù)組

數(shù)組是由索引到值的映射,這意味這數(shù)組可以有空缺,索引的個(gè)數(shù)小于數(shù)組的長(zhǎng)度說(shuō)明數(shù)組為空缺數(shù)組。

var a = new Array(5);
a[1] = 1;
a[4] = 4;

// a[0], a[2], a[3]都未賦值,a為空缺數(shù)組
二十六、數(shù)組中某些方法會(huì)忽略空缺 1. 數(shù)組遍歷方法 1) forEach()遍歷時(shí)會(huì)跳過(guò)空缺
["a", , "b"].forEach(function (x, i) { console.log(i + ": " + x); });

// 0: a
// 2: b
2) every()也會(huì)跳過(guò)空缺(類似的還有some()方法)
["a", , "b"].every(function (x) { return typeof x === "string" });

// true
3) map()雖然會(huì)跳過(guò)空缺,但會(huì)保留空缺
["a", , "b"].map(function (x, i) { return i + "." + x; });
// ["0.a", , "2.b"]
4) filter()會(huì)去除空缺
["a", , "b"].filter(function (x) { return true; });
// ["a", "b"]
2. 其他方法 1) join()會(huì)把空缺、undefined、null轉(zhuǎn)換成空的字符串
["a", , "b"].join("-");
// a--b

["a", , "b", undefined, "c", null,"d"].join("-");
//a--b--c--d
2) sort()排序時(shí)保留空缺
["a", , "b"].sort();
// ["a", "b", ,]
3. for-in循環(huán)

for-in循環(huán)可以正確列出屬性建, 跳過(guò)空缺

for (var key in ["a", , "b"]) { console.log(key) }
// 0
// 2

for (var key in ["a", undefined, "b"]) { console.log(key) }
// 0
// 1
// 2
4. Function.prototype.apply()

apply()把每個(gè)空缺轉(zhuǎn)化為undefined參數(shù)。

function f () { return Array.prototype.slice.call(arguments); }
f.apply(null, [,,,]);
// [undefined, undefined, undefined]

Array.apply(null, [,,,]);
// [undefined, undefined, undefined]
二十七、數(shù)組構(gòu)造函數(shù)

Array.isArray(obj) 判斷obj是否為一個(gè)數(shù)組,能夠正確處理跨域?qū)ο蟆?/p> 二十八、數(shù)組的原型方法 1. 添加和刪除元素(破壞性的) 1) Array.prototype.shift()

移除索引0處的元素并返回該元素。隨后元素的索引依次減1:

var arr = ["a", "b"];
var first = arr.shift(); // "a"
console.log(arr); // ["b"]
2) Array.prototype.unshift(elem1?, elem2?, ...)

在數(shù)組前面插入指定的元素,返回新的數(shù)組長(zhǎng)度

var arr = ["a", "b"];
arr.unshift("c", "d"); // 4
console.log(arr); // ["c", "d", "a", "b"]
3) Array.prototype.pop()

移除數(shù)組最后的元素并返回該元素

var arr = ["a", "b"];
var last = arr.pop(); // "b"
console.log(arr); // ["a"]
4) Array.prototype.push(elem1?, elem2?, ...)

在數(shù)組的最后追加指定的元素,返回新的數(shù)組長(zhǎng)度

var arr = ["a", "b"];
arr.push("c", "d"); // 4
console.log(arr); // ["a", "b", "c", "d"]

小技巧: 可以使用apply函數(shù)將一個(gè)數(shù)組追加到另一個(gè)數(shù)組的后面

var arr1 = ["a", "b"];
var arr2 = ["c", "d"];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // ["a", "b", "c", "d"]
5) Array.prototype.splice(start, deleteCount?, elem1?, elem2?, ...)

從索引start位置開始,刪除deleteCount個(gè)元素,并在該位置插入給定元素, 返回刪除的元素組成的數(shù)組

var arr = ["a", "b", "c", "d"];
arr.splice(1, 2, "X"); // ["b", "c"]
console.log(arr); // ["a", "X", "d"]

注: start可以為負(fù)值,表示從倒數(shù)幾位開始。deleteCount是可選的,如果省略,移除從start位置開始的所有元素

var arr = ["a", "b", "c", "d"];
arr.splice(-2); // ["c", "d"]
console.log(arr); // ["a", "d"]
2. 排序和顛倒元素順序(破壞性的) 1) Array.prototype.reverse()

顛倒數(shù)組中的元素,并返回指向原數(shù)組的引用:

var arr = ["a", "b", "c"];
arr.reverse(); // ["c", "b", "a"]
console.log(arr); // ["c", "b", "a"]
2) Array.prototype.sort(compareFunction?)

數(shù)組排序, 并返回排序后的數(shù)組

var arr = ["banana", "apple", "pear", "orange"];
arr.sort() // ["apple", "banana", "orange", "pear"];
console.log(arr); // ["apple", "banana", "orange", "pear"];

注: 排序是通過(guò)將元素轉(zhuǎn)換為字符串再進(jìn)行比較,這意味著數(shù)字不是按照數(shù)值進(jìn)行排序

[-1, -20, 7, 50].sort(); // [-1, -20, 50, 7]

可以通過(guò)compareFunction來(lái)解決該問(wèn)題,該函數(shù)的簽名為:

function compareFunction (a, b)

比較參數(shù)a和b的值,返回的規(guī)則如下:

小于0的整數(shù), a < b, 則a排在b的前面

等于0, a === b

大于0的整數(shù), a > b, 則a排在b的后面

注: 對(duì)于數(shù)字,一般的就簡(jiǎn)單的返回a-b, 可能導(dǎo)致數(shù)值溢出,為了防止這種情況,可能需要更復(fù)雜的邏輯

[-1, -20, 7, 50].sort(function (a, b) {
  return a < b ? -1 : (a > b ? 1 : 0);
}); // [-20, -1, 7, 50]
3. 合并、切分和連接(非破壞性) 1) Array.prototype.concat(arr1?, arr2?, ...)

創(chuàng)建一個(gè)新數(shù)組,其中包含接受者的所有元素,其次是arr1中的所有元素,依次類推,如果其中一個(gè)參數(shù)不是數(shù)組, 當(dāng)中元素添加到數(shù)組中

var arr = ["a", "b"];
var newArray = arr.concat("c", ["d", "e"]); // ["a", "b", "c", "d", "e"]
console.log(newArray); // ["a", "b", "c", "d", "e"]
console.log(arr); // ["a", "b"]
2) Array.prototype.slice(start?, end?)

把數(shù)組中從start開始到end(不包含end)的元素復(fù)制到新數(shù)組中

["a", "b", "c", "d"].slice(1, 3) // ["b", "c"]

["a", "b", "c", "d"].slice(1) // ["b", "c", "d"]
["a", "b", "c", "d"].slice() // ["a", "b", "c", "d"]

注: 不包含end時(shí),拷貝從start開始到最后的所有元素, 如果不傳start和end參數(shù),拷貝數(shù)組, start和end都可以是負(fù)值,表示從倒數(shù)開始

3) Array.prototype.join(separator?)

對(duì)所有數(shù)組元素應(yīng)用toString()創(chuàng)建字符串, 并使用separator連接字符,如果缺少separator,默認(rèn)使用","

[3, 4, 5].join("-") // 3-4-5
[3, 4, 5].join() // 3,4,5
[3, 4, 5].join("") // 345

注:如果數(shù)組中某個(gè)元素為undefined, null或者空缺, 調(diào)用join方法是,會(huì)將該元素轉(zhuǎn)換成空字符串

[undefined, null, "a"].join("#") // ##a
[undefined, , "a"].join("#") // ##a
4. 值的查找(非破壞性) 1) Array.prototype.indexOf(searchValue, startIndex?)

從數(shù)組的startIndex位置開始查找searchValue,返回第一次出現(xiàn)searchValue的索引,沒(méi)有找到,就返回-1。缺少startIndex, 查找整個(gè)數(shù)組

[3, 1, 17, 1, 4].indexOf(1); // 1
[3, 1, 17, 1, 4].indexOf(1, 2); // 3

注:查找時(shí)使用的是嚴(yán)格相等, 不能查找NaN

[NaN].indexOf(NaN); // -1
2) Array.prototype.lastIndexOf(searchValue, startIndex?)

從數(shù)組的startIndex位置開始反向查找searchValue,返回第一次出現(xiàn)searchValue的索引,沒(méi)有找到,就返回-1。缺少startIndex, 查找整個(gè)數(shù)組。查找時(shí)使用的是嚴(yán)格相等

[3, 1, 17, 1, 4].indexOf(1); // 3
[3, 1, 17, 1, 4].indexOf(1, -3); // 1
[3, 1, 17, 1, 4].indexOf(1, 2); // 1
5. 迭代(非破壞性)

可以劃分為三種迭代方法:

檢查方法: 主要觀察數(shù)組的內(nèi)容(forEach, every, some)

轉(zhuǎn)化方法: 從已有的數(shù)組中獲得新數(shù)組(map, filter)

歸約方法: 基于接受者的元素計(jì)算出結(jié)果(reduce, reduceRight)

1) Array.prototype.forEach(callback, thisValue?)

遍歷數(shù)組中的元素

var arr = ["apple", "banana", "pear"];
arr.forEach(function (elem) {
    console.log(elem);
});
// apple
// banana
// pear

注: 存在一個(gè)缺陷,不支持break或者類似于提前終止循環(huán)的處理,除非throw Error。

2) Array.prototype.every(callback, thisValue?)

如果對(duì)每個(gè)元素?;卣{(diào)函數(shù)都返回true,則every方法返回true, 如果某個(gè)元素回調(diào)函數(shù)返回false, 則停止迭代。類似全稱量詞

// 檢查數(shù)組中的元素是否全部為偶數(shù)
function isEven(x) { return x % 2 === 0 }
[2, 4, 6].every(isEven); // true
[2, 4, 5].every(isEven); // false

注: 如果為空數(shù)組,返回true,不會(huì)調(diào)用callback方法

[].every(function () { throw new Error("Empty array") }); // true
3) Array.prototype.some(callback, thisValue?)

如果對(duì)其中某個(gè)元素?;卣{(diào)函數(shù)返回true,則some方法返回true, 如果某個(gè)元素回調(diào)函數(shù)返回true, 則停止迭代。類似存在量詞

// 檢查數(shù)組中的元素是否存在偶數(shù)
function isEven(x) { return x % 2 === 0 }
[1, 3, 5].some(isEven); // false
[2, 2, 3].some(isEven); // true

注: 如果為空數(shù)組,返回false,不會(huì)調(diào)用callback方法

[].some(function () { throw new Error("Empty array") }); // false
4) Array.prototype.map(callback, thisValue?)

轉(zhuǎn)化數(shù)組的每個(gè)元素都是原數(shù)組中元素調(diào)用回調(diào)函數(shù)callback后的結(jié)果

[1, 2, 3],map(function (elem) { return 2 * elem; }); // [2, 4, 6]
5) Array.prototype.filter(callback, thisValue?)

轉(zhuǎn)化數(shù)組的元素都是原數(shù)組中元素調(diào)用回調(diào)函數(shù)callback返回true的元素

[1, 0, 3, 0].filter(function (x) { return !!x; }); // [1, 3]
6) Array.prototype.reduce(callback, initialValue?)

從左至右進(jìn)行迭代,其中callback參數(shù)的結(jié)構(gòu)為:

function callback(previousValue, currentValue, currentIndex, array);

除初次調(diào)用外,每次調(diào)用callback時(shí),參數(shù)previousValue是上一次回調(diào)函數(shù)的返回值。初次調(diào)用回調(diào)函數(shù)有兩種情況

提供顯式initialValue參數(shù),previousValue就是initialValue,而currentValue為數(shù)組中的第一個(gè)元素

未提供顯式initialValue參數(shù),previousValue就是第一個(gè)元素,而currentValue為數(shù)組中的第二個(gè)元素

reduce方法返回最后一次調(diào)用回調(diào)函數(shù)時(shí)的結(jié)果

function add (pre, cur) {
    return pre + cur;
}

[1, 10, -3].reduce(add); // 8

注: 只有一個(gè)元素的數(shù)組調(diào)用reduce,則返回該元素

function add (pre, cur) {
    return 2 * pre + 3 * cur;
}

function add2 (pre, cur) {
    return 1;
}

[7].reduce(add); // 7
[7].reduce(add2); // 7

注: 如果對(duì)空數(shù)組調(diào)用reduce, 必須指定initialValue, 否則會(huì)拋出異常

[].reduce(add);
// Uncaught TypeError: Reduce of empty array with no initial value
7) Array.prototype.reduceRight(callback, initialValue?)

工作原來(lái)與Array.prototype.reduce相似,但是是從右至左歸約

二十九、類數(shù)組對(duì)象

javascript中存在一類對(duì)象看起來(lái)像數(shù)組,實(shí)際上不是,可以通過(guò)索引訪問(wèn)元素具有l(wèi)ength屬性,但沒(méi)有數(shù)組的其他實(shí)例屬性。

類數(shù)組對(duì)象主要有:特殊對(duì)象arguments、DOM節(jié)點(diǎn)列表和字符串。

我們可以使用泛型方法來(lái)使類數(shù)組對(duì)象防訪問(wèn)數(shù)組原型上的方法。

三十、正則表達(dá)式原子(分組)

分組的語(yǔ)法:

(<>) 捕獲分組。任何匹配pattern的內(nèi)容都可以通過(guò)反向引用訪問(wèn)或作為匹配結(jié)果。

(?:<>) 非捕獲分組。仍然根據(jù)pattern匹配,但不保存捕獲的內(nèi)容。分組沒(méi)有數(shù)字可以引用。

12...依次類推稱為方向引用;他們指向之前匹配的分組。第一個(gè)數(shù)字必須不是0

/^(a+)-1$/.test("a-a"); // true
/^(a+)-1$/.test("aaa-aaa"); // true
/^(a+)-1$/.test("aaa-a"); // false

注:方向引用保證破折號(hào)前后的字符數(shù)一致

使用方向引用來(lái)匹配HTML標(biāo)簽

var tagName = /<([^>]+)>[^<]*/;
tagName.exec("bold")[1] // b

tagName.exec("text")[1] // strong
tagName.exec("text")[1] // TypeError: Cannot read property "1" of null
三十一、正則表達(dá)式量詞

? 表示從未匹配或只匹配一次

表示從匹配零次或多次

表示匹配一次或多次

{n} 表示完全匹配n次

{n, } 表示匹配至少n次

{n, m} 表示匹配至少n次,最多m次

默認(rèn)情況下,量詞是貪婪匹配的,他們會(huì)盡可能多的匹配,如果想使用勉強(qiáng)匹配(盡可能少),可以通過(guò)量詞后面加問(wèn)號(hào)(?)

// 貪婪匹配
" ".match(/^<(.*)>/)[1] // a>  ".match(/^<(.*?)>/)[1] // a

注:*?是十分有用的模式,它可以匹配一切,直到后面的原子出現(xiàn)。
上述匹配HTML標(biāo)簽的正則可以改為

var tagName = /<(.+?)>.*?/;
tagName.exec("bold")[1] // b

tagName.exec("text")[1] // strong
tagName.exec("text")[1] // TypeError: Cannot read property "1" of null
三十二、正則表達(dá)式斷言

^ 只匹配輸入的開始位置

$ 只匹配輸入結(jié)束位置

b 只匹配單詞的邊界。不要與[b]混淆,它匹配一個(gè)退格。

B 只匹配非單詞邊界

(?=<>) 正向肯定斷言:只匹配pattern所匹配的接下來(lái)的內(nèi)容。pattern只是用來(lái)向前查找,但會(huì)忽略匹配的pattern部分

(?!<>) 正向肯定斷言:只匹配pattern不匹配的接下來(lái)的內(nèi)容。pattern只是用來(lái)向前查找,但會(huì)忽略匹配的pattern部分

匹配單詞邊界

/ell/.test("hello"); // false
/ell/.test("ello"); // false
/ell/.test("a ell v"); // true

通過(guò)B匹配單詞的內(nèi)部元素

/BellB/.test("ell"); // false
/BellB/.test("ello"); // false
/BellB/.test("hello"); // true
三十三、正則表達(dá)式標(biāo)識(shí)

標(biāo)識(shí)是正則表達(dá)式字面量的后綴和正則表達(dá)式構(gòu)造函數(shù)的參數(shù);它修改正則表達(dá)是的匹配行為。

簡(jiǎn)稱 全稱 描述
g global 給定的正則表達(dá)式可以匹配多次,它會(huì)影響幾種方法,尤其是String.prototype.replace()
i ignoreCase 試圖匹配給定的正則表達(dá)式時(shí)忽略大小寫
m multiline 在多行模式時(shí),開始操作符^和結(jié)束操作符$匹配每一行,而不是輸入的整個(gè)字符串

簡(jiǎn)稱用于正則字面量后綴和構(gòu)造函數(shù)參數(shù),全稱用于正則表達(dá)式對(duì)象的屬性

三十四、正則表達(dá)式的實(shí)例屬性

標(biāo)識(shí): 布爾值表示設(shè)置什么標(biāo)志。

global(全局): 是否設(shè)置/g標(biāo)識(shí)
ignoreCase(忽略大小寫): 是否設(shè)置了/i標(biāo)識(shí)
multiline(多行): 是否設(shè)置/m標(biāo)識(shí)

多次匹配數(shù)據(jù)(設(shè)置了/g標(biāo)識(shí))

lastIndex: 下次繼續(xù)查找的起始索引

var regex = /abc/i;
regex.ignoreCase; // true
regex.multiline; // false
三十五、RegExp.prototype.test: 是否存在匹配

test()方法用來(lái)檢查正則表達(dá)式regex是否匹配字符串str:

regex.test(str)

如果沒(méi)有設(shè)置/g標(biāo)識(shí),該方法只檢查是否在str某處存在匹配;如果設(shè)置了/g標(biāo)識(shí),則該方法會(huì)多次匹配regex并返回true,屬性lastIndex包含最后一次匹配之后的索引

// 未設(shè)置/g
var str = "_x_x";
/x/.test(str); // true
/a/.test(str); // false

// 設(shè)置/g
var regex = /x/g;
regex.lastIndex; // 0

regex.test(str); // true
regex.lastIndex; // 2

regex.test(str); // true
regex.lastIndex; // 4

regex.test(str); // false
三十六、String.prototype.search: 匹配位置的索引

search()方法查找str匹配regex的位置

str.search(regex)

如果存在匹配返回匹配位置的索引,否則,返回值為-1, 進(jìn)行查找時(shí),regex的global和lastIndex屬性被忽略(其中l(wèi)astIndex沒(méi)有改變)

"abba".search(/b/); // true
"abba".search(/B/i); // true
"abba".search(/x/i); // true

注:如果search()的參數(shù)不是正則表達(dá)式,它被轉(zhuǎn)換為正則:

"aaab".search("^a+b+$"); // 0
三十七、RegExp.prototype.exec: 捕獲分組

在str匹配regex的同時(shí)捕獲分組

var matchData = regex.exec(str);

如果沒(méi)有匹配,matchData為null。否則,matchData為匹配結(jié)果,是帶有兩個(gè)附屬屬性的數(shù)組
(1) 數(shù)組元素

元素0是完整正則表達(dá)式的匹配結(jié)果。

元素n>1是捕獲的分組N。

(2)屬性

input 是輸入的完整字符串

index 是查找到匹配處的索引

如果未設(shè)置/g標(biāo)識(shí),只返回第一次匹配的結(jié)果:

var regex = /a(b+)/;
regex.exec("_abbb_ab_");
// ["abbb", "bbb", index: 1, input: "_abbb_ab_"]
regex.lastIndex; // 0

如果設(shè)置了/g標(biāo)識(shí),可以反復(fù)調(diào)用exec()方法返回所有的匹配項(xiàng),返回值null表示沒(méi)有任何匹配。屬性lastIndex表示下次匹配從哪里開始

var regex = /a(b+)/g;
var str = "_abbb_ab_";
console.log(regex.exec(str));
// ["abbb", "bbb", index: 1, input: "_abbb_ab_"]
console.log(regex.lastIndex); // 5

console.log(regex.exec(str));
// ["ab", "b", index: 6, input: "_abbb_ab_"]
console.log(regex.lastIndex); // 8

regex.exec(str); // null

使用循環(huán)遍歷所有的匹配項(xiàng)

var regex = /a(b+)/g;
var str = "_abbb_ab_";
var match;
while(match = regex.exec(str)) {
    console.log(match[1]);
}

// bbb
// b
三十八、String.prototype.match: 捕獲分組已經(jīng)返回所有匹配的子字符串
var matchData = str.match(regex);

如果未設(shè)置/g標(biāo)識(shí),該方法類似與RegExp.prototype.exec()

"abba".match(/a(b+)/);
// ["abb", "bb", index: 0, input: "abba"]

如果設(shè)置了/g標(biāo)識(shí),則返回str中含有所有匹配的子字符串的數(shù)組;如果沒(méi)有任何匹配,則返回null

"_abbb_ab_".match(/a(b+)/g);
// ["abbb", "ab"]
三十九、String.prototype.replace: 查找和替換

存在兩個(gè)參數(shù): search, replacement

search: 字符串或者正則表達(dá)式。

1) 字符串: 在字符串中找到匹配的字面量,只能替換一次出現(xiàn)的匹配項(xiàng),暫不存在
    (replaceAll函數(shù)),想要替換多次出現(xiàn)的匹配項(xiàng),必須使用正則表達(dá)式/g標(biāo)識(shí)。
2) 正則表達(dá)式: 對(duì)輸入的字符串進(jìn)行匹配。如果想替換多次,必須使用/g標(biāo)識(shí)

replacement: 字符串或者函數(shù)。

1) 字符串: 描述如何替換找到的匹配項(xiàng)), 使用該字符串替換匹配項(xiàng),替換字符串中的$
符號(hào)允許使用完全匹配或者匹配分組進(jìn)行替換
2) 函數(shù): 執(zhí)行替換并提供參數(shù)匹配信息.

"iixxxixx".replace("i", "o") // oixxxixx
"iixxxixx".replace(/i/, "o") // oixxxixx
"iixxxixx".replace(/i/g, "o") // ooxxxoxx

// 使用$符號(hào)
"iixxxixx".replace(/i+/g, "($&)") // (ii)xxx(i)xx
"iixxxixx".replace(/(i+)/g, "($1)") // (ii)xxx(i)xx

// 使用函數(shù)替換
function repl(search, group, offset, input) {
    return "{ search: " + search.toUpperCase() + ", group: " + group + ", offset: " + offset + " }";
}
"iixxxixx".replace(/(i+)/g, repl)
// { search: II, group: ii, offset: 0 }xxx{ search: I, group: i, offset: 5 }xx
1. replacement為字符串

內(nèi)容用來(lái)逐字替換匹配項(xiàng),唯一例外是特殊字符美元符號(hào)($),它會(huì)啟動(dòng)替換指令

分組:$n在匹配中插入分組n。n必須大于等于1($0沒(méi)有任何特殊含義)

匹配的子字符串:

1) $` (反引號(hào))插入匹配項(xiàng)之前的文本
2) $& 插入完整的匹配項(xiàng)
3) $" (單引號(hào))插入匹配項(xiàng)之后的文本

$$ 插入單個(gè)$字符

"axb cxd".replace(/x/g, "($`,$&,$")"); // a(a,x,b cxd)b c(axb c,x,d)d
""foo" and "bar"".replace(/"(.*?)"/g, "#$1#"); // #foo# and #bar#
2. replacement為函數(shù)

如果replacement為函數(shù),它需要對(duì)替換匹配項(xiàng)的字符串進(jìn)行處理。簽名如下:

function replacement (search, group_1, ..., group_n, offset, input){}

search與前面介紹的$&(完整的匹配項(xiàng))相同, offset表示找到匹配項(xiàng)的位置,input是正在被匹配的字符串

search: 正則表達(dá)式匹配到的字符串

group: 如果存在分組,該值為匹配到的分組值, 可變參數(shù), 匹配到分組有多少個(gè),這個(gè)參數(shù)就有多少個(gè), 如果不存在,表示匹配到子字符所在原字符串的位置

offset(倒數(shù)第二個(gè)參數(shù)): 匹配到子字符所在原字符串的位置

input(最后一個(gè)參數(shù)): 原字符串

function replaceFunc (match) { return 2 * match; }
"3 peoples and 5 oranges".replace(/d+/g, replaceFunc); // 6 peoples and 10 oranges
四十、標(biāo)識(shí)符/g的一些問(wèn)題

正則表達(dá)式設(shè)置了/g標(biāo)識(shí),有些方法必須多次(循環(huán))調(diào)用才能放回所有結(jié)果。這些方法如下所示

RegExp.prototype.test()

RegExp.prototype.exec()

正則表達(dá)式作為迭代器成為結(jié)果序列的指針時(shí),會(huì)被不正確地使用。這導(dǎo)致的問(wèn)題如下:

1. 帶有/g的正則表達(dá)式不能內(nèi)聯(lián)
// 反模式
var count = 0;
while (/a/g.test("babaa")) count++;

// 正確用法
var count = 0;
var regex = /a/g;
while (regex.test("babaa")) count++;

上述第一種情況中會(huì)創(chuàng)建無(wú)限循環(huán),每次循環(huán)迭代都會(huì)創(chuàng)建一個(gè)新的正則表達(dá)式,導(dǎo)致重新開始迭代。

// 反模式
function extractQuoted(str) {
    var match;
    var result = [];
    while ((match = /"(.*?)"/g.exec(str)) !== null) {
        result.push(match[1]);
    }
    return result;
}
// 會(huì)導(dǎo)致無(wú)限循環(huán)

// 正確的方法
function extractQuoted(str) {
    var QUOTE_REGEX = /"(.*?)"/g;
    var match;
    var result = [];
    while ((match = QUOTE_REGEX.exec(str)) !== null) {
        result.push(match[1]);
    }
    return result;
}

extractQuoted(""hello", "world""); // ["hello", "world"]

注:為了避免上述這種無(wú)限循環(huán)的情況,最好的解決辦法就是在任何情況下,都不使用內(nèi)聯(lián)正則表達(dá)式,這要求我們形成一個(gè)良好的編碼習(xí)慣。

2. 帶/g的正則表達(dá)式作為參數(shù)

需要多次調(diào)用test()和exec()方法時(shí),把正則作為參數(shù)傳遞給方法時(shí)必須要小心。必須設(shè)置/g標(biāo)識(shí),為了安全起見(jiàn),應(yīng)該設(shè)置lastIndex為0

3. 共享帶有/g的正則表達(dá)式

當(dāng)你引用不是新創(chuàng)建的正則表達(dá)式時(shí),在把它作為迭代器前,需要手動(dòng)把lastIndex設(shè)置為0。由于迭代依賴lastIndex,這種正則表達(dá)式不能同時(shí)用于多個(gè)迭代。

function countOccurrences(regex, str) {
    var count = 0;
    while (regex.test(str)) count++;
    return count;
}

countOccurrences(/x/g, "_x_x"); // 2

// 問(wèn)題一: 如果不加/g標(biāo)識(shí),會(huì)進(jìn)入無(wú)限循環(huán)
countOccurrences(/x/, "_x_x"); // 無(wú)限循環(huán)

// 問(wèn)題二: lastIndex未設(shè)置為0
var regex = /x/g;
regex.lastIndex = 2;
countOccurrences(regex, "_x_x"); // 1

// 修復(fù)上述兩個(gè)問(wèn)題
function countOccurrences(regex, str) {
    if (!regex.global) {
        throw new Error("Please set flag /g of regex");
    }

    var origLastIndex = regex.lastIndex; // store
    regex.lastIndex = 0;

    var count = 0;
    while (regex.test(str)) count++;

    regex.lastIndex = origLastIndex;
    return count;
}

// 更簡(jiǎn)單的方式,使用String.prototype.match
function countOccurrences(regex, str) {
    if (!regex.global) {
        throw new Error("Please set flag /g of regex");
    }

    return (str.match(regex) || []).length;
}
四十一、引用文本

給制定的字符串拼裝成正則表達(dá)式,所有特殊是字符都需要進(jìn)行轉(zhuǎn)義。

function quoteText(text) {
    return text.replace(/[^$.*+?()[]{}|=!<>:-]/g, "$&");
}

console.log(quoteText("*All* (most?) aspects.")); // *All* (most?) aspects.
四十二、缺少斷言(^、$)的正則表達(dá)式可以在任意位置匹配
/aa/.test("xaay"); // true
/^aa$/.test("xaay"); // false
四十三、匹配一切或者什么都不匹配

一種特殊情況:函數(shù)可以把正則表達(dá)式當(dāng)做參數(shù),用于過(guò)濾,如果缺少這個(gè)參數(shù),需要提供一個(gè)可以匹配一切的默認(rèn)值

1. 匹配一切

空的正則表達(dá)式可以匹配一切

new RegExp("").test("dfadsfdas"); // true
new RegExp("").test(""); // true

空的正則表達(dá)式應(yīng)該是//, 但是它被解釋為JavaScript的注釋。所有我們可以使用最接近的字面量代替/(?:)/(空的非捕獲分組)。這個(gè)分組可以匹配一切而且不捕獲任何字符串。

new RegExp(""); // /(?:)/
2. 不匹配任何字符

空的正則表達(dá)式相反的正則表達(dá)式

var never = /.^/;
never.test("asdsad"); // false
never.test(""); // false
四十四、正則表達(dá)式備忘錄 1. 原子

.(點(diǎn)) 匹配除了行結(jié)束符的一切字符。使用[sS]可以正則匹配一切

轉(zhuǎn)義字符

d 匹配數(shù)字([0-9]); D 匹配非數(shù)字([^0-9])。
w 匹配拉丁字母數(shù)字的字符以及下劃線([a-zA-Z0-9_]); W 匹配其他字符。
s 匹配所有空白字符(空格、制表、換行符等); S 匹配所有的非空白字符。
需要轉(zhuǎn)移的字符: * . ? + $ ^ [ ] ( ) { } |  /

字符類(字符集合): [...]和[^...]

源字符: [abc](除了]-的所有匹配其本身的字符)
轉(zhuǎn)義字符: [dw]
范圍: [A-Za-z0-9]

分組

捕獲分組: (...); 方向引用1
非捕獲分組: (?:...)

2. 量詞

貪婪匹配

? * +
{n}, {n, }, {n, m}

非貪婪: 把?放在任何貪婪量詞后面

3. 斷言

輸入的開始和結(jié)束: ^ $。

單詞的邊界,非單詞邊界: b B。

正向肯定查找: (?=...) 匹配緊隨其后的模式,但其會(huì)被忽略

正向否定查找: (?!...) 不匹配緊隨其后的模式,但其會(huì)被忽略

4. 析取(或): | 5. 創(chuàng)建正則表達(dá)式

字面量: /abc/i (加載時(shí)編譯)

構(gòu)造函數(shù): new RegExp("zxc", "igm"); (運(yùn)行時(shí)編譯)

6. 標(biāo)識(shí)

global(全局): /g(影響正則表達(dá)式的一些方法)。

ignoreCase(忽略大小寫): /i 。

multiline(多行): /m (^和$匹配每一行,而不是完整的輸入)。

7. 方法

regexp.test(str): 是否存在匹配

不設(shè)置`/g`: 是否在某處存在匹配
設(shè)置`/g`: 存在多少次匹配就返回多少次true

str.search(regex): 在哪個(gè)所有存在匹配

regexp.exec(str): 捕獲分組

不設(shè)置`/g`: 只捕獲第一次匹配的分組
設(shè)置`/g`: 捕獲所有匹配的分組

str.match(regexp): 捕獲分組或返回所有匹配的字符串

不設(shè)置`/g`: 捕獲分組
設(shè)置`/g`: 返回所有匹配的子字符串?dāng)?shù)組

str.replace(search, replacement): 查找和替換

search: 字符串和正則表達(dá)式(使用后者,設(shè)置/g)
replacement: 字符串(使用$1, 以此類推)或函數(shù)(arguments[1]是分組1, 以此類推)返回字符串

四十五、文字的編碼和解碼 1. encodeURI(uri)

在uri中我們用百分號(hào)來(lái)編碼特殊字符,除了下列字符,其余的特殊字符都會(huì)被編碼。

URI字符: ; , / ? : @ & = + $ #

下面字符也不會(huì)被編碼: a-z A-Z 0-9 - _ . ! ~ * " ( )

encodeURI("http://example.com/Fur Elise/"); // http://example.com/Fur%20Elise/
2. encodeURIComponent(uri)

除了下列字符,所有字符都會(huì)被百分號(hào)編碼(URI字符也會(huì)被編碼):

下面字符也不會(huì)被編碼: a-z A-Z 0-9 - _ . ! ~ * " ( )

encodeURIComponent("http://example.com/Fur Elise/"); // http%3A%2F%2Fexample.com%2FFur%20Elise%2F
3. decodeURI(encodeURI)

對(duì)已經(jīng)進(jìn)行encodeURI編碼的uri進(jìn)行解碼操作

decodeURI("http://example.com/Fur%20Elise/"); // http://example.com/Fur Elise/
4. decodeURIComponent(encodeURIComponent)

對(duì)已經(jīng)進(jìn)行encodeURIComponent編碼的uri進(jìn)行解碼操作, 所有的百分號(hào)編碼都會(huì)被解碼

decodeURIComponent("http%3A%2F%2Fexample.com%2FFur%20Elise%2F"); // http://example.com/Fur Elise/
四十六、Console在IE9中存在兼容性問(wèn)題

在Internet Explorer9中存在一個(gè)bug。在IE9中,console對(duì)象只有當(dāng)開發(fā)者工具欄被打開過(guò)至少一次,才會(huì)存在。
這意味著如果你的代碼引用了console對(duì)象,同時(shí)又沒(méi)有預(yù)先打開開發(fā)者工具欄,你可能會(huì)得到一個(gè)引用錯(cuò)誤。
為了確保兼容性,最好在使用console對(duì)象之前先判斷其是否存在。

四十七、模塊系統(tǒng) 1. CommonJS模塊(CommonJS Module, CJS)

CJS的主要化身是Node.js模塊,其特點(diǎn):

緊湊的語(yǔ)法

同步加載的設(shè)計(jì)

主要用于服務(wù)端

2. 異步模塊定義(Asynchronous Module Definition, AMD)

AMD 最典型的實(shí)現(xiàn)就是Requirejs, 其特點(diǎn):

AMD語(yǔ)法稍微復(fù)雜,但不通過(guò)eval()或者靜態(tài)編譯步驟就可以工作

異步加載的設(shè)計(jì)

主要用于瀏覽器

四十八、算法: ToPrimitive() —— 將值轉(zhuǎn)換為原始值

要將任意值轉(zhuǎn)換成數(shù)字或者字符串,首先會(huì)被轉(zhuǎn)換成任意的原始值,然后在轉(zhuǎn)換成最終的結(jié)果。

ECMAScript規(guī)范中有一個(gè)內(nèi)部函數(shù), ToPrimitive()(不能訪問(wèn)),能夠?qū)崿F(xiàn)這個(gè)功能。簽名如下:

ToPrimitive(input, PreferredType?)

可選參數(shù)PreferredType表明轉(zhuǎn)換后餓類型:它可以是NumberString,具體取決于ToPrimitive的結(jié)果是希望轉(zhuǎn)換成數(shù)字還是字符串

如果PreferredTypeNumber,會(huì)執(zhí)行以下步驟。

(1) 如果input是原始值,返回這個(gè)值。

(2) 否則,如果input是對(duì)象,調(diào)用input.valueOf()。如果結(jié)果是原始值,返回結(jié)果。

(3) 否則,調(diào)用input.toString()。如果結(jié)果是原始值,返回結(jié)果。

(4) 否則,拋出一個(gè)TypeError(說(shuō)明輸入轉(zhuǎn)換原始值出錯(cuò)了)

如果PreferredTypeString,會(huì)執(zhí)行以下步驟。

(1) 如果input是原始值,返回這個(gè)值。

(2) 否則,如果input是對(duì)象,調(diào)用input.toString()。如果結(jié)果是原始值,返回結(jié)果。

(3) 否則,調(diào)用input.valueOf()。如果結(jié)果是原始值,返回結(jié)果。

(4) 否則,拋出一個(gè)TypeError(說(shuō)明輸入轉(zhuǎn)換原始值出錯(cuò)了)

PreferredType也可以省略,這種情況下,日期會(huì)被認(rèn)為是String而其他值會(huì)被認(rèn)為是Number。因此+操作符和===運(yùn)算符可以操作ToPrimitive()。

ToPrimitive()實(shí)戰(zhàn)
valueOf的默認(rèn)實(shí)現(xiàn)會(huì)返回this,而toString()的默認(rèn)實(shí)現(xiàn)會(huì)返回類型信息

var empty = {};
empty.valueOf() === empty; // true
empty.toString(); // "[object Object]"

Number() 跳過(guò)了valueOf()并且將toString()執(zhí)行結(jié)果轉(zhuǎn)換為數(shù)字,所以,它將"[object Object]"轉(zhuǎn)換成了NaN

Number({}); // NaN

下面對(duì)象重寫了valueOf(), 這會(huì)影響Number(), 但是不會(huì)對(duì)String()造成任何改變

var n = { valueOf: function () { return 123; } };
Number(n); // 123
String(n); // "[object Object]"

下面對(duì)象重寫了toString()方法,因?yàn)榻Y(jié)果會(huì)轉(zhuǎn)換成數(shù)字,Number()返回了一個(gè)數(shù)字

var s = { toString: function () { return "7"; } };
String(s); // "7"
Number(s); // 7

注: 個(gè)人筆記,持續(xù)更新

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/81643.html

相關(guān)文章

  • JavaScript易錯(cuò)知識(shí)點(diǎn)整理

    摘要:知識(shí)點(diǎn)變量作用域上方的函數(shù)作用域中聲明并賦值了,且在之上,所以遵循就近原則輸出等于。上方的函數(shù)作用域中被重新賦值,未被重新聲明,且位于之下,所以輸出全局作用域中的。上方利用方法進(jìn)行對(duì)象的深拷貝可以避免源對(duì)象被篡改的可能。 前言 本文是我學(xué)習(xí)JavaScript過(guò)程中收集與整理的一些易錯(cuò)知識(shí)點(diǎn),將分別從變量作用域,類型比較,this指向,函數(shù)參數(shù),閉包問(wèn)題及對(duì)象拷貝與賦值這6個(gè)方面進(jìn)行由...

    vincent_xyb 評(píng)論0 收藏0
  • JavaScript易錯(cuò)知識(shí)點(diǎn)整理

    摘要:知識(shí)點(diǎn)變量作用域上方的函數(shù)作用域中聲明并賦值了,且在之上,所以遵循就近原則輸出等于。上方的函數(shù)作用域中被重新賦值,未被重新聲明,且位于之下,所以輸出全局作用域中的。若執(zhí)行則會(huì)輸出。上方利用方法進(jìn)行對(duì)象的深拷貝可以避免源對(duì)象被篡改的可能。 前言 本文是我學(xué)習(xí)JavaScript過(guò)程中收集與整理的一些易錯(cuò)知識(shí)點(diǎn),將分別從變量作用域,類型比較,this指向,函數(shù)參數(shù),閉包問(wèn)題及對(duì)象拷貝與賦值...

    2shou 評(píng)論0 收藏0
  • JavaScript:面試頻繁出現(xiàn)的幾個(gè)易錯(cuò)點(diǎn)

    摘要:針對(duì)于面向?qū)ο缶幊痰摹R驗(yàn)槊嫦驅(qū)ο缶褪轻槍?duì)對(duì)象例子中的守候來(lái)進(jìn)行執(zhí)行某些動(dòng)作。這就是閉包的用途之一延續(xù)變量周期。把變量放在閉包里面和放在全局變量里面,影響是一致的。 1.前言 這段時(shí)間,金三銀四,很多人面試,很多人分享面試題。在前段時(shí)間,我也臨時(shí)擔(dān)任面試官,為了大概了解面試者的水平,我也寫了一份題目,面試了幾個(gè)前端開發(fā)者。在這段時(shí)間里面,我在學(xué),在寫設(shè)計(jì)模式的一些知識(shí),想不到的設(shè)計(jì)模式...

    VincentFF 評(píng)論0 收藏0
  • JavaScript文章

    摘要:我對(duì)知乎前端相關(guān)問(wèn)題的十問(wèn)十答張?chǎng)涡駨場(chǎng)涡翊笊駥?duì)知乎上經(jīng)典的個(gè)前端問(wèn)題的回答。作者對(duì)如何避免常見(jiàn)的錯(cuò)誤,難以發(fā)現(xiàn)的問(wèn)題,以及性能問(wèn)題和不好的實(shí)踐給出了相應(yīng)的建議。但并不是本身有問(wèn)題,被標(biāo)準(zhǔn)定義的是極好的。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老...

    mumumu 評(píng)論0 收藏0
  • 前端基礎(chǔ)入門

    摘要:手把手教你做個(gè)人火的時(shí)候,隨便一個(gè)都能賺的盆滿缽滿,但是,個(gè)人沒(méi)有服務(wù)端,沒(méi)有美工,似乎就不能開發(fā)了,真的是這樣的嗎秘密花園經(jīng)典的中文手冊(cè)。涵蓋前端知識(shí)體系知識(shí)結(jié)構(gòu)圖書推薦以及入門視頻教程,全的簡(jiǎn)直不要不要的了。 JavaScript 實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制指定區(qū)域文本 html5 的 webAPI 接口可以很輕松的使用短短的幾行代碼就實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制區(qū)域文本的功能,不需要依賴 flash。...

    shinezejian 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<