你需要了解的ES6語法大總結(jié)
前言
ES6已結(jié)出來6年多了,相信大家的ES6常用語法都用的爐火純青了,自己打算把ES6的語法全部總結(jié)一遍,也方便自己更加的靈活使用和鞏固知識(shí)。希望能對(duì)你有幫助!
let
介紹
let 語句聲明一個(gè)塊級(jí)作用域的本地變量,并且可選的將其初始化為一個(gè)值。新的變量的聲明方式。
它具有如下的特性
不允許重復(fù)聲明
var可以多次重復(fù)聲明(最后一次聲明會(huì)覆蓋前面的聲明),而let不能(會(huì)報(bào)錯(cuò)),可以避免重復(fù)命名
var a = 1; var a = 2; console.log(a); // 2
let a = 1; let a = 2; console.log(a); // Uncaught SyntaxError: Identifier 'a' has already been declared
這個(gè)特性有一大好處就是避免多人開發(fā)時(shí),自己或者別人命名了相同名稱的變量,把以前的變量給覆蓋掉了。
塊級(jí)作用域
為什么需要塊級(jí)作用域?
ES5時(shí)只有全局作用域和函數(shù)作用域,沒有塊級(jí)作用域,這帶來很多不合理的場景。
第一種場景,內(nèi)層變量可能會(huì)覆蓋外層變量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world'; // 這里會(huì)有變量提升
}
}
f(); // undefinedif代碼塊的外部使用外層的tmp變量,內(nèi)部使用內(nèi)層的tmp變量。但是,函數(shù)f執(zhí)行后,輸出結(jié)果為undefined,原因在于變量提升,導(dǎo)致內(nèi)層的tmp變量覆蓋了外層的tmp變量。
第二種場景,用來計(jì)數(shù)的循環(huán)變量泄露為全局變量。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
// for循環(huán)外面打印
console.log(i); // 5上面代碼中,變量i只用來控制循環(huán),但是循環(huán)結(jié)束后,它并沒有消失,泄露成了全局變量。
es6的塊級(jí)作用域
{
let a = 10;
var b = 1;
}
console.log(b); // 1
console.log(a); // Uncaught ReferenceError: a is not definedlet實(shí)際上為 JavaScript 新增了塊級(jí)作用域,let聲明的變量只在它所在的代碼塊有效,外層拿不到let聲明的變量。上面代碼中{}就是塊級(jí)作用域
ES6 允許塊級(jí)作用域的任意嵌套。
{{{{
{let insane = 'Hello World'}
console.log(insane); // 報(bào)錯(cuò)
}}}};上面代碼使用了一個(gè)五層的塊級(jí)作用域,每一層都是一個(gè)單獨(dú)的作用域。第四層作用域無法讀取第五層作用域的內(nèi)部變量。
內(nèi)層作用域可以定義外層作用域的同名變量。
{{{{
let insane = 'Hello World';
{let insane = 'Hello World'}
}}}};for循環(huán)的計(jì)數(shù)器,就很合適使用let命令。
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i); // ReferenceError: i is not defined上面代碼中,計(jì)數(shù)器i只在for循環(huán)體內(nèi)有效,在循環(huán)體外引用就會(huì)報(bào)錯(cuò)。
改成var聲明的話
for (var i = 0; i < 3; i++) {
console.log(i); //輸出0 1 2
}
console.log(i); //只會(huì)輸出3如果想要更加深入的研究for循環(huán)作用域的問題,請(qǐng)參考這篇 文章
暫時(shí)性死區(qū)
var a = 1
{
a = 6
let a // Uncaught ReferenceError: Cannot access 'a' before initialization
}在代碼塊內(nèi),使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱為暫時(shí)性死區(qū) ES6 規(guī)定暫時(shí)性死區(qū),主要是為了減少運(yùn)行時(shí)錯(cuò)誤,防止在變量聲明前就使用這個(gè)變量,從而導(dǎo)致意料之外的行為。這樣的錯(cuò)誤在 ES5 是很常見的,現(xiàn)在有了這種規(guī)定,避免此類錯(cuò)誤就很容易了。
變量提升
關(guān)于是否有變量提升,目前來看并不統(tǒng)一。阮一峰的 ECMAScript 6 入門中的let和const章節(jié)中明確說明 不存在變量提升。但自己的理解還是存在變量提升的。下面舉例說明一下:
var a = 1;
(function () {
console.log(a); // 1
})();我們簡單改造一下
var a = 1;
(function () {
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 2
})();從這里其實(shí)可以看出let也是存在變量提升的,只是在變量賦值之前不能對(duì)變量進(jìn)行讀寫,否則就會(huì)報(bào)錯(cuò),這也就是暫時(shí)性死區(qū)。
變量不會(huì)掛載到window
在本人看來,var聲明的變量掛載到window是一種很不好的設(shè)計(jì),這很容易會(huì)導(dǎo)致變量被污染,以及全局變量被濫用。所以,新的聲明方式已經(jīng)不將聲明的變量再掛載到window上面了。
// var聲明的變量會(huì)掛載到window上 var a = 1; window.a // 1 // let聲明的變量不會(huì)掛載到window let b = 1; window.b // undefined
頂層對(duì)象的屬性與全局變量掛鉤,被認(rèn)為是 JavaScript 語言最大的設(shè)計(jì)敗筆之一。這樣的設(shè)計(jì)帶來了幾個(gè)很大的問題,首先是沒法在編譯時(shí)就報(bào)出變量未聲明的錯(cuò)誤,只有運(yùn)行時(shí)才能知道(因?yàn)槿肿兞靠赡苁琼攲訉?duì)象的屬性創(chuàng)造的,而屬性的創(chuàng)造是動(dòng)態(tài)的);其次,程序員很容易不知不覺地就創(chuàng)建了全局變量(比如打字出錯(cuò));最后,頂層對(duì)象的屬性是到處可以讀寫的,這非常不利于模塊化編程。另一方面,window對(duì)象有實(shí)體含義,指的是瀏覽器的窗口對(duì)象,頂層對(duì)象是一個(gè)有實(shí)體含義的對(duì)象,也是不合適的。
從 ES6 開始,全局變量將逐步與頂層對(duì)象的屬性脫鉤。
const
const聲明一個(gè)只讀的常量。一旦聲明,常量的值就不能改變。其他特性和let一樣。
const a = 1; a = 3; // TypeError: Assignment to constant variable.
const聲明的變量不得改變值,這意味著,const一旦聲明變量,就必須立即初始化,不能留到以后賦值。
const a; // SyntaxError: Missing initializer in const declaration
const實(shí)際上保證的,并不是變量的值不得改動(dòng),而是變量指向的那個(gè)內(nèi)存地址所保存的數(shù)據(jù)不得改動(dòng)。對(duì)于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值),值就保存在變量指向的那個(gè)內(nèi)存地址,因此等同于常量。但對(duì)于復(fù)合類型的數(shù)據(jù)(主要是對(duì)象和數(shù)組),變量指向的內(nèi)存地址,保存的只是一個(gè)指向?qū)嶋H數(shù)據(jù)的指針,const只能保證這個(gè)指針是固定的(即總是指向另一個(gè)固定的地址),至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了。因此,將一個(gè)對(duì)象聲明為常量必須非常小心。
const a = {};
// 為 a 添加一個(gè)屬性,可以成功
a.prop = 123;
// 將 a 指向另一個(gè)對(duì)象,就會(huì)報(bào)錯(cuò)
a = {}; // TypeError: "a" is read-only總結(jié)
對(duì)于var的使用:
我們需要明白一個(gè)事實(shí),var所表現(xiàn)出來的特殊性:比如作用域提升、window全局對(duì)象、沒有塊級(jí)作用域等都是一些歷史遺留問題;是JavaScript在設(shè)計(jì)之初的一種語言缺陷
當(dāng)然目前也在利用這種缺陷出一系列的面試題,來考察大家對(duì)JavaScript語言本身以及底層的理解
但是在實(shí)際工作中,我們可以使用最新的規(guī)范來編寫,也就是不再使用var來定義變量了
對(duì)于let和const:
對(duì)于let和const來說,是目前開發(fā)中推薦使用的
我們推薦使用const,這樣可以保證數(shù)據(jù)的安全性不會(huì)被隨意的篡改
只有當(dāng)我們明確知道一個(gè)變量后續(xù)會(huì)需要被重新賦值時(shí),這個(gè)時(shí)候再使用let
反正就一句話,以后不要再用var啦!
解構(gòu)賦值
ES6 允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)
對(duì)象的解構(gòu)
以前的取值方式
const obj = { a:1, b:2, c:3 }
const a = obj.a;
const b = obj.b;
const c = obj.c; 現(xiàn)在的取值方式
const obj = { a:1, b:2, c:3 }
const {a,b,c} = obj;修改解構(gòu)出來的名稱
const obj = { a:1, b:2, c:3 }
const {a:a1, b:b1, c} = obj;
console.log(a1) // 1
console.log(b1) // 2
console.log(c) // 3給默認(rèn)值
const obj = { a:1, b:2, c:3 }
const {d = 5} = obj;
const {e:e1 = 6} = obj;
console.log(d) // 5
console.log(e1) // 6深層對(duì)象的解構(gòu)
const metadata = {
title: "english-title",
translations: [
{
title: "我是深處的title",
},
],
friend: {
girlFriend: {
name: {
firstName: "chimmy",
},
},
},
};
let {
title: englishTitle, // rename
translations: [
{
title: localeTitle, // rename
},
],
friend: {
girlFriend: {
name: { firstName },
},
},
} = metadata;
console.log(englishTitle); // "english-title"
console.log(localeTitle); // "我是深處的title"
console.log(firstName); // "chimmy"數(shù)組的解構(gòu)
// 以前獲取數(shù)組里面值得方式 var names = ["abc", "cba", "nba"] // var item1 = names[0] // var item2 = names[1] // var item3 = names[2] // 對(duì)數(shù)組的解構(gòu): [] let [item1, item2, item3] = names console.log(item1, item2, item3) // abc cba nba // 解構(gòu)后面的元素 let [, , itemz] = names console.log(itemz) // nba // 解構(gòu)出一個(gè)元素,后面的元素放到一個(gè)新數(shù)組中 let [itemx, ...newNames] = names console.log(itemx, newNames) // abc ['cba', 'nba'] // 解構(gòu)的默認(rèn)值 let [itema, itemb, itemc, itemd = "aaa"] = names console.log(itemd) // aaa // 通過解構(gòu)交換變量 let a = 1; let b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1
函數(shù)參數(shù)解構(gòu)
函數(shù)的參數(shù)也可以使用解構(gòu)賦值。
function add([x, y]){
return x + y;
}
add([1, 2]); // 3函數(shù)參數(shù)的解構(gòu)也可以使用默認(rèn)值。
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]對(duì)象字面量增強(qiáng)寫法和計(jì)算屬性名
let name = "jimmy"
let age = 18
// 屬性的簡寫
let obj = {
name,
age
}
// 等同于
let obj = {
name:name,
age:age
}
// 方法的簡寫
let obj2 = {
bar() {
console.log(this)
},
}
// 等同于
let obj2 = {
bar:function() {
console.log(this)
}
}
// 計(jì)算屬性名(對(duì)象的鍵可以是變量)
let obj3 = {}
obj3[name] = "chimmy";
console.log(obj3.jimmy); // chimmy展開語法( ... )
展開語法(Spread syntax), 可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時(shí), 將數(shù)組表達(dá)式或者string在語法層面展開;還可以在構(gòu)造字面量對(duì)象時(shí), 將對(duì)象表達(dá)式按key-value的方式展開。(字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 這種簡潔的構(gòu)造方式)
示例
const names = ["abc", "cba", "nba"]
const info = {name: "why", age: 18}
// 1.函數(shù)調(diào)用時(shí)
function foo(x, y, z) {
console.log(x, y, z) // abc cba nba
}
foo(...names)
// 2.構(gòu)造數(shù)組時(shí)
const newNames = [...names]
console.log(newNames) // ['abc', 'cba', 'nba']
console.log(...[1, 2, 3]) // 1 2 3
// 3.構(gòu)建對(duì)象字面量時(shí)ES2018(ES9)
const obj = { ...info, address: "成都市", ...names }
console.log(obj) // {0: 'abc', 1: 'cba', 2: 'nba', name: 'why', age: 18, address: '成都市'}復(fù)制數(shù)組(淺拷貝)
數(shù)組是復(fù)合的數(shù)據(jù)類型,直接復(fù)制的話,只是復(fù)制了指向底層數(shù)據(jù)結(jié)構(gòu)的指針,而不是克隆一個(gè)全新的數(shù)組。
const a1 = [1, 2]; const a2 = a1; a2[0] = 2; console.log(a1) // [2, 2]
const a1 = [1, 2]; const a2 = [...a1]; a2[0] = 2; console.log(a1) // [1, 2]
合并數(shù)組
const arr1 = ['a', 'b']; const arr2 = ['c']; const arr3 = ['d', 'e']; // ES5 的合并數(shù)組 arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ] // ES6 的合并數(shù)組 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
模板字符串
ES6之前拼接字符串和其他標(biāo)識(shí)符
const name = "jimmy";
const age = 18;
const height = 1.88;
console.log("my name is " + name + ", age is " + age + ", height is " + height)ES6提供的模板字符串
const age = 18;
const height = 1.88;
// 支持變量
const message = `my name is ${name}, age is ${age}, height is ${height}`;
console.log(message); // my name is , age is 18, height is 1.88
// 支持表達(dá)式
const info = `age double is ${age * 2}`;
console.log(info); // age double is 36
// 支持函數(shù)調(diào)用
function doubleAge() {
return age * 2;
}
const info2 = `double age is ${doubleAge()}`;
console.log(info2); // double age is 36對(duì)象擴(kuò)展
object.is()
語法
Object.is(value1, value2);
被比較的第一個(gè)值。value1
被比較的第二個(gè)值。 value2
介紹
ES5 比較兩個(gè)值是否相等,只有兩個(gè)運(yùn)算符:相等運(yùn)算符(==)和嚴(yán)格相等運(yùn)算符(===)。它們都有缺點(diǎn),前者會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型,后者的NaN不等于自身,以及+0等于-0。JavaScript 缺乏一種運(yùn)算,在所有環(huán)境中,只要兩個(gè)值是一樣的,它們就應(yīng)該相等。
ES6 提出“Same-value equality”(同值相等)算法,用來解決這個(gè)問題。Object.is就是部署這個(gè)算法的新方法。它用來比較兩個(gè)值是否嚴(yán)格相等,與嚴(yán)格比較運(yùn)算符(===)的行為基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false不同之處只有兩個(gè):一是+0不等于-0,二是NaN等于自身。
console.log(NaN === NaN); // false console.log(0 === -0); // true Object.is(NaN, NaN) // true Object.is(+0, -0) // false
Object.assign()
Object.assign() 方法用于將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象分配到目標(biāo)對(duì)象。它將返回目標(biāo)對(duì)象。
// 目標(biāo)對(duì)象與源對(duì)象有同名屬性,或多個(gè)源對(duì)象有同名屬性,則后面的屬性會(huì)覆蓋前面的屬性。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target); // { a: 1, b: 4, c: 5 } 注意目標(biāo)對(duì)象自身也會(huì)改變
console.log(returnedTarget); { a: 1, b: 4, c: 5 }
// Object.assign()的返回值其實(shí)就是目標(biāo)對(duì)象
target === returnedTarget // true語法
Object.assign(target, ...sources)
- target 目標(biāo)對(duì)象。
- sources 源對(duì)象。 個(gè)數(shù)沒有限制
返回值為 目標(biāo)對(duì)象
如果只有一個(gè)參數(shù),Object.assign()會(huì)直接返回該參數(shù)。
const obj = {a: 1};
Object.assign(obj) === obj // true如果該參數(shù)不是對(duì)象,則會(huì)先轉(zhuǎn)成對(duì)象,然后返回。
typeof Object.assign(2) // "object"
由于undefined和null無法轉(zhuǎn)成對(duì)象,所以如果它們作為參數(shù),就會(huì)報(bào)錯(cuò)。
Object.assign(undefined) // 報(bào)錯(cuò)
Object.assign(null) // 報(bào)錯(cuò)
// 如果`undefined`和`null`不在首參數(shù),就不會(huì)報(bào)錯(cuò)。
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true常見用途
(1)為對(duì)象添加屬性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}上面方法通過Object.assign()方法,將x屬性和y屬性添加到Point類的對(duì)象實(shí)例。
(2)為對(duì)象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同于下面的寫法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};上面代碼使用了對(duì)象屬性的簡潔表示法,直接將兩個(gè)函數(shù)放在大括號(hào)中,再使用assign()方法添加到SomeClass.prototype之中。
(3)克隆對(duì)象
function clone(origin) {
return Object.assign({}, origin);
}注意,這種方式是淺拷貝。詳細(xì)理解 請(qǐng)參考 js深拷貝和淺拷貝知多少
(4)合并多個(gè)對(duì)象
將多個(gè)對(duì)象合并到某個(gè)對(duì)象。
const merge = (target, ...sources) => Object.assign(target, ...sources);
如果希望合并后返回一個(gè)新對(duì)象,可以改寫上面函數(shù),對(duì)一個(gè)空對(duì)象合并。
const merge = (...sources) => Object.assign({}, ...sources);(5)為屬性指定默認(rèn)值
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
console.log(options);
// ...
}上面代碼中,DEFAULTS對(duì)象是默認(rèn)值,options對(duì)象是用戶提供的參數(shù)。Object.assign()方法將DEFAULTS和options合并成一個(gè)新對(duì)象,如果兩者有同名屬性,則options的屬性值會(huì)覆蓋DEFAULTS的屬性值。
對(duì)象的遍歷方式(擴(kuò)展)
如何能夠遍歷出對(duì)象中每個(gè)key和value的值呢?
let obj = {
name: "jimmy",
age: 18,
like: "girl",
};主要有以下方式
// for...in的作用是用于遍歷對(duì)象的。
for (let key in obj) {
console.log(key, obj[key]);
}
// Object.keys()用于返回對(duì)象所有key組成的數(shù)組。
Object.keys(obj).forEach((key) => {
console.log(key, obj[key]);
});
// Object.getOwnPropertyNames()用于返回對(duì)象所有key組成的數(shù)組。
Object.getOwnPropertyNames(obj).forEach((key) => {
console.log(key, obj[key]);
});
// Reflect.ownKeys()用于返回對(duì)象所有key組成的數(shù)組。
Reflect.ownKeys(obj).forEach((key) => {
console.log(key, obj[key]);
});
// 打印的都是
// name jimmy
// age 18
// like girlfunction擴(kuò)展
函數(shù)默認(rèn)值
ES6 之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值,只能采用變通的方法。
function log(x, y) {
if (typeof y === 'undefined' || typeof y === 'null') {
y = 'World';
}
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World當(dāng)一個(gè)函數(shù)有很多參數(shù)涉及初始化的時(shí)候,這樣寫代碼極其丑陋。ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面。
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // HelloES6 的寫法還有兩個(gè)好處:首先,閱讀代碼的人,可以立刻意識(shí)到哪些參數(shù)是可以省略的,不用查看函數(shù)體或文檔;其次,有利于將來的代碼優(yōu)化,即使未來的版本在對(duì)外接口中,徹底拿掉這個(gè)參數(shù),也不會(huì)導(dǎo)致以前的代碼無法運(yùn)行。
rest參數(shù)
ES6 引入 rest 參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了。rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10上面代碼的add函數(shù)是一個(gè)求和函數(shù),利用 rest 參數(shù),可以向該函數(shù)傳入任意數(shù)目的參數(shù)。
下面是一個(gè) rest 參數(shù)代替arguments變量的例子。
// arguments變量的寫法
function sortNumbers() {
return Array.from(arguments).sort();
}
// rest參數(shù)的寫法
const sortNumbers = (...numbers) => numbers.sort();上面代碼的兩種寫法,比較后可以發(fā)現(xiàn),rest 參數(shù)的寫法更自然也更簡潔。
注意,rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù)),否則會(huì)報(bào)錯(cuò)。
// 報(bào)錯(cuò)
function f(a, ...b, c) {
// ...
}箭頭函數(shù)
箭頭函數(shù)可以說是 ES6 很大的福利了,不管你是函數(shù)式愛好者還是面向?qū)ο箝_發(fā)者,函數(shù)是必須要用到的東西。之前聲明函數(shù)需要使用 function,如下:
function hello() {
console.log('say hello')
}
// 或
let hello = function() {
console.log('say hello')
}現(xiàn)在可以這樣做了:
let hello = () => {
console.log('say hello')
}如果帶參數(shù)該怎么做呢?
let hello = (name) => {
console.log('say hello', name)
}
// 或者
let hello = name => {
console.log('say hello', name)
}
// 如果只有一個(gè)參數(shù),可以省略括號(hào),如果大于一個(gè)參數(shù)一定要記得帶括號(hào)函數(shù)的聲明和參數(shù)寫的很清楚了,那么對(duì)于返回值有什么要注意的地方呢?
如果返回值是表達(dá)式可以省略 return 和 {}
let pow = x => x * x
如果返回值是字面量對(duì)象
let person = (name) => ({
age: 20,
addr: 'Beijing City'
})箭頭函數(shù)注意點(diǎn)
箭頭函數(shù)中沒有this,內(nèi)部的this就是定義時(shí)上層作用域中的this。也就是說,箭頭函數(shù)內(nèi)部的this指向是固定的
不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以對(duì)箭頭函數(shù)使用new命令,否則會(huì)拋出一個(gè)錯(cuò)誤。
箭頭函數(shù)不可以使用arguments對(duì)象,該對(duì)象在函數(shù)體內(nèi)不存在。如果要用,可以用 rest 參數(shù)代替。
不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。
函數(shù)的length屬性
在函數(shù)體內(nèi),有時(shí)候需要判斷函數(shù)有幾個(gè)參數(shù),一共有2個(gè)辦法。在 ES5 中可以在函數(shù)體內(nèi)使用 arguments 來判斷。
function foo(a, b = 1, c) {
console.log(arguments.length)
}
foo('a', 'b') //2然而在 ES6 中不能再使用 arguments 來判斷了,但可以借助 Function.length 來判斷。
function foo(a, b = 1, c) {
console.log(foo.length)
}
foo('a', 'b') // 1細(xì)心的同學(xué)發(fā)現(xiàn) Function.length 結(jié)果和 arguments 的結(jié)果不同!沒錯(cuò),F(xiàn)unction.length 是統(tǒng)計(jì)第一個(gè)默認(rèn)參數(shù)前面的變量數(shù):
函數(shù)指定了默認(rèn)值以后,函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個(gè)數(shù)。
數(shù)組的擴(kuò)展
Array.from
介紹
Array.from方法用于將兩類對(duì)象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對(duì)象(array-like object)和可遍歷(iterable)的對(duì)象(包括 ES6 新增的數(shù)據(jù)結(jié)構(gòu) Set 和 Map)。
語法
Array.from(arrayLike[, mapFn[, thisArg]])
- arrayLike 想要轉(zhuǎn)換成數(shù)組的偽數(shù)組對(duì)象或可迭代對(duì)象。
- mapFn 可選 如果指定了該參數(shù),新數(shù)組中的每個(gè)元素會(huì)執(zhí)行該回調(diào)函數(shù)。
- thisArg 可選 執(zhí)行回調(diào)函數(shù)mapFn時(shí)this對(duì)象
下面是一個(gè)類似數(shù)組的對(duì)象,Array.from將它轉(zhuǎn)為真正的數(shù)組。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的寫法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的寫法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']實(shí)際應(yīng)用中,常見的類似數(shù)組的對(duì)象是 DOM 操作返回的 NodeList 集合,以及函數(shù)內(nèi)部的arguments對(duì)象。Array.from都可以將它們轉(zhuǎn)為真正的數(shù)組。
// NodeList對(duì)象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
return p.textContent.length > 100;
});
// arguments對(duì)象
function foo() {
var args = Array.from(arguments);
// ...
}
// Set
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set); // [ "foo", "bar", "baz" ]
// Map
const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map); // [[1, 2], [2, 4], [4, 8]]如果參數(shù)是一個(gè)真正的數(shù)組,Array.from會(huì)返回一個(gè)一模一樣的新數(shù)組。
Array.from([1, 2, 3]) // [1, 2, 3]
Array.from可以接受第二個(gè)參數(shù),作用類似于數(shù)組的map方法,用來對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。
Array.from(arrayLike, x => x * x); // 等同于 Array.from(arrayLike).map(x => x * x); Array.from([1, 2, 3], (x) => x * x) // [1, 4, 9]
for...of
ES6中新增的數(shù)組遍歷方式
for (let val of [1, 2, 3]) {
console.log(val); // 1,2,3
}Array.prototype.find()
介紹
find() 方法返回?cái)?shù)組中滿足提供的測(cè)試函數(shù)的第一個(gè)元素的值,否則返回 undefined。
const array1 = [5, 12, 8, 130, 44]; const found = array1.find(element => element > 10); console.log(found); //12
語法
arr.find(callback[, thisArg])
callback 在數(shù)組每一項(xiàng)上執(zhí)行的函數(shù),接收 3 個(gè)參數(shù):
element當(dāng)前遍歷到的元素。 index 可選 當(dāng)前遍歷到的索引 array 數(shù)組本身
thisArg 執(zhí)行回調(diào)時(shí)用作this 的對(duì)象。
Array.prototype.findIndex()
findIndex()方法返回?cái)?shù)組中滿足提供的測(cè)試函數(shù)的第一個(gè)元素的索引。否則返回-1。其實(shí)這個(gè)和 find() 是成對(duì)的,不同的是它返回的是索引而不是值。
let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
return element > 10;
});
console.log(found); // 1Array.prototype.fill()
介紹
fill() 方法用一個(gè)固定值填充一個(gè)數(shù)組中從起始索引到終止索引內(nèi)的全部元素。不包括終止索引。
語法
arr.fill(value[, start[, end]])
value 用來填充數(shù)組元素的值 start 可選 起始索引 默認(rèn)值為0 end 可選 終止索引 默認(rèn)值為this.length 返回值 修改后的數(shù)組
如果 start 是個(gè)負(fù)數(shù), 則開始索引會(huì)被自動(dòng)計(jì)算成為 length+start, 其中 length 是 this 對(duì)象的 length 屬性值。如果 end 是個(gè)負(fù)數(shù), 則結(jié)束索引會(huì)被自動(dòng)計(jì)算成為 length+end。
const array1 = [1, 2, 3, 4]; console.log(array1.fill(0, 2, 4)); // [1, 2, 0, 0] console.log(array1.fill(5, 1)); // [1, 5, 5, 5] // 只有一個(gè)參數(shù),說明其他兩項(xiàng)都是默認(rèn)值,會(huì)替換數(shù)組全部內(nèi)容 console.log(array1.fill(6)); // [6, 6, 6, 6]
Array.prototype.copyWithin()
數(shù)組實(shí)例的copyWithin()方法,在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員復(fù)制到其他位置(會(huì)覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個(gè)方法,會(huì)修改當(dāng)前數(shù)組。
Array.prototype.copyWithin(target, start = 0, end = this.length)
它接受三個(gè)參數(shù)。
- target(必需):從該位置開始替換數(shù)據(jù)。如果為負(fù)值,表示倒數(shù)。
- start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0。如果為負(fù)值,表示從末尾開始計(jì)算。
- end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度。如果為負(fù)值,表示從末尾開始計(jì)算。
// 將3號(hào)位復(fù)制到0號(hào)位 [1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5] // -2相當(dāng)于3號(hào)位,-1相當(dāng)于4號(hào)位 [1, 2, 3, 4, 5].copyWithin(0, -2, -1) // [4, 2, 3, 4, 5] // 參數(shù)不足三個(gè),沒有的參數(shù)就是默認(rèn)值 [1, 2, 3, 4, 5].copyWithin(-2) // [1, 2, 3, 1, 2] [1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5]
Array.of()
Array.of()方法用于將一組值,轉(zhuǎn)換為數(shù)組。
Array.of(3, 11, 8) // [3,11,8] Array.of(3) // [3] Array.of(3).length // 1
這個(gè)方法的主要目的,是彌補(bǔ)數(shù)組構(gòu)造函數(shù)Array()的不足。因?yàn)閰?shù)個(gè)數(shù)的不同,會(huì)導(dǎo)致Array()的行為有差異。
Array() // [] Array(3) // [, , ,] Array(3, 11, 8) // [3, 11, 8]
面代碼中,Array()方法沒有參數(shù)、一個(gè)參數(shù)、三個(gè)參數(shù)時(shí),返回的結(jié)果都不一樣。只有當(dāng)參數(shù)個(gè)數(shù)不少于 2 個(gè)時(shí),Array()才會(huì)返回由參數(shù)組成的新數(shù)組。參數(shù)只有一個(gè)正整數(shù)時(shí),實(shí)際上是指定數(shù)組的長度。
Array.of()基本上可以用來替代Array()或new Array(),并且不存在由于參數(shù)不同而導(dǎo)致的重載。它的行為非常統(tǒng)一。
Array.of() // [] `Array.of()`總是返回參數(shù)值組成的數(shù)組。如果沒有參數(shù),就返回一個(gè)空數(shù)組。 Array.of(undefined) // [undefined] Array.of(1) // [1] Array.of(1, 2) // [1, 2]
Number 擴(kuò)展
Number.isFinite()
用來檢查一個(gè)數(shù)值是否為有限的(finite),即不是Infinity。
Number.isFinite(15) // true
Number.isFinite(0.8) // true
Number.isFinite(NaN) // false
Number.isFinite(Infinity) // false
Number.isFinite(-Infinity) // false
Number.isFinite('foo') // false
Number.isFinite('15') // false
Number.isFinite(true) // false注意,如果參數(shù)類型不是數(shù)值,Number.isFinite一律返回false。
Number.isNaN()
用來檢查一個(gè)值是否為NaN。
Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true如果參數(shù)類型不是NaN,Number.isNaN一律返回false。
Number.isInteger()
用來判斷一個(gè)數(shù)值是否為整數(shù)。
Number.isInteger(25) // true
Number.isInteger(25.1) // false
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // falseNumber.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER
JavaScript 能夠準(zhǔn)確表示的整數(shù)范圍在-2^53到2^53之間(不含兩個(gè)端點(diǎn)),超過這個(gè)范圍,無法精確表示這個(gè)值。
Math.pow(2, 53) // 9007199254740992 9007199254740992 // 9007199254740992 9007199254740993 // 9007199254740992 Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
上面代碼中,超出 2 的 53 次方之后,一個(gè)數(shù)就不精確了。
ES6 引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER這兩個(gè)常量,用來表示這個(gè)范圍的上下限。
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1 // true Number.MAX_SAFE_INTEGER === 9007199254740991 // true Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER // true Number.MIN_SAFE_INTEGER === -9007199254740991 // true
Number.isSafeInteger()
JavaScript 能夠準(zhǔn)確表示的整數(shù)范圍在-2^53到2^53之間(不含兩個(gè)端點(diǎn)),超過這個(gè)范圍,無法精確表示這個(gè)值。
Math.pow(2, 53) // 9007199254740992 Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
Number.parseInt(),Number.parseFloat()
ES6 將全局方法parseInt(), parseFloat()移植到Number對(duì)象上面,行為完全保持不變。這樣做的目的,是逐步減少全局性方法,使得語言逐步模塊化。
String擴(kuò)展
String.prototype.includes()
ES5中可以使用indexOf方法來判斷一個(gè)字符串是否包含在另一個(gè)字符串中,indexOf返回出現(xiàn)的下標(biāo)位置,如果不存在則返回-1。
const str = 'jimmy'
console.log(str.indexOf('y')) // 4ES6提供了includes方法來判斷一個(gè)字符串是否包含在另一個(gè)字符串中,返回boolean類型的值。
const str = 'jimmy'
console.log(str.includes('mm')) // true
// 區(qū)分大小寫
'Blue Whale'.includes('blue'); // returns false語法
str.includes(searchString[, position])
- searchString 要在此字符串中搜索的字符串。
- position 從當(dāng)前字符串的哪個(gè)索引位置開始搜尋子字符串,默認(rèn)值為 0。
返回值
如果當(dāng)前字符串包含被搜尋的字符串,就返回 true;否則返回 false。;
String.prototype.startsWith()
判斷參數(shù)字符串是否在原字符串的頭部, 返回boolean類型的值。
const str = 'jimmy'
console.log(str.startsWith('ji')) // trueString.prototype.endsWith()
判斷參數(shù)字符串是否在原字符串的尾部, 返回boolean類型的值。
const str = 'jimmy'
console.log(str.endsWith('my')) // trueString.prototype.repeat()
repeat方法返回一個(gè)新字符串,表示將原字符串重復(fù)n次。
const str = 'jimmy' const newStr = str.repeat(2) console.log(newStr) // jimmyjimmy
Symbol
ES6 引入了一種新的原始數(shù)據(jù)類型 Symbol ,表示獨(dú)一無二的值。它是 JavaScript 語言的第七種數(shù)據(jù)類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數(shù)值(Number)、對(duì)象(Object)。
為什么要引入Symbol呢
ES5 的對(duì)象屬性名都是字符串,這容易造成屬性名的沖突。比如,你使用了一個(gè)他人提供的對(duì)象,但又想為這個(gè)對(duì)象添加新的方法(mixin 模式),新方法的名字就有可能與現(xiàn)有方法產(chǎn)生沖突。如果有一種機(jī)制,保證每個(gè)屬性的名字都是獨(dú)一無二的就好了,這樣就從根本上防止屬性名的沖突。這就是 ES6 引入Symbol的原因。
Symbol 值通過Symbol函數(shù)生成。這就是說,對(duì)象的屬性名現(xiàn)在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的 Symbol 類型。凡是屬性名屬于 Symbol 類型,就都是獨(dú)一無二的,可以保證不會(huì)與其他屬性名產(chǎn)生沖突。
let a = Symbol(); let b = Symbol(); typeof a // symbol console.log(a === b); // false
Symbol函數(shù)可以接受一個(gè)字符串作為參數(shù),表示對(duì) Symbol 實(shí)例的描述,主要是為了在控制臺(tái)顯示,或者轉(zhuǎn)為字符串時(shí),比較容易區(qū)分。
let s1 = Symbol('foo')
let s2 = Symbol('foo')
console.log(s1) //Symbol(foo)
console.log(s2) // Symbol(foo)
// `Symbol`函數(shù)的參數(shù)只是表示對(duì)當(dāng)前 Symbol 值的描述,因此相同參數(shù)的`Symbol`函數(shù)的返回值是不相等的。
console.log(s1 === s2) // false注意
Symbol函數(shù)前不能使用new命令,否則會(huì)報(bào)錯(cuò)。這是因?yàn)樯傻?Symbol 是一個(gè)原始類型的值,不是對(duì)象。也就是說,由于 Symbol 值不是對(duì)象,所以不能添加屬性。基本上,它是一種類似于字符串的數(shù)據(jù)類型。
如果 Symbol 的參數(shù)是一個(gè)對(duì)象,就會(huì)調(diào)用該對(duì)象的toString方法,將其轉(zhuǎn)為字符串,然后才生成一個(gè) Symbol 值。
const obj = {
toString() {
return 'abc';
}
};
const sym = Symbol(obj); // Symbol(abc)Symbol 值不能與其他類型的值進(jìn)行運(yùn)算,會(huì)報(bào)錯(cuò)。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to stringSymbol 值可以顯式轉(zhuǎn)為字符串,布爾值 但是不能轉(zhuǎn)為數(shù)值。
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
Boolean(sym) // true
!sym // false
Number(sym) // TypeError
sym + 2 // TypeErrorSymbol.for()
Symbol.for() 接受一個(gè)字符串作為參數(shù),然后搜索有沒有以該參數(shù)作為名稱的 Symbol 值。如果有,就返回這個(gè) Symbol 值,否則就新建一個(gè)以該字符串為名稱的 Symbol 值,并將其注冊(cè)到全局。
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1 === s2) // trueSymbol.for()與Symbol()這兩種寫法,都會(huì)生成新的 Symbol。它們的區(qū)別是,前者會(huì)被登記在全局環(huán)境中供搜索,后者不會(huì)。Symbol.for()不會(huì)每次調(diào)用就返回一個(gè)新的 Symbol 類型的值,而是會(huì)先檢查給定的key是否已經(jīng)存在,如果不存在才會(huì)新建一個(gè)值。
Symbol.keyFor()
Symbol.keyFor()方法返回一個(gè)已登記的 Symbol 類型值的key。
const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined
const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // foo應(yīng)用場景
消除魔術(shù)字符串
魔術(shù)字符串指的是,在代碼之中多次出現(xiàn)、與代碼形成強(qiáng)耦合的某一個(gè)具體的字符串或者數(shù)值。風(fēng)格良好的代碼,應(yīng)該盡量消除魔術(shù)字符串,改由含義清晰的變量代替。
function getArea(shape, options) {
let area = 0;
switch (shape) {
case 'Triangle': // 魔術(shù)字符串
area = .5 * options.width * options.height;
break;
/* ... more code ... */
}
return area;
}
getArea('Triangle', { width: 100, height: 100 }); // 魔術(shù)字符串上面代碼中,字符串Triangle和Circle就是魔術(shù)字符串。它多次出現(xiàn),與代碼形成“強(qiáng)耦合”,不利于將來的修改和維護(hù)。
常用的消除魔術(shù)字符串的方法,就是把它寫成一個(gè)變量。
const shapeType = {
triangle: 'Triangle'
};
function getArea(shape, options) {
let area = 0;
switch (shape) {
case shapeType.triangle:
area = .5 * options.width * options.height;
break;
}
return area;
}
getArea(shapeType.triangle, { width: 100, height: 100 });上面代碼中,我們把Triangle寫成shapeType對(duì)象的triangle屬性,這樣就消除了強(qiáng)耦合。
如果仔細(xì)分析,可以發(fā)現(xiàn)shapeType.triangle等于哪個(gè)值并不重要,只要確保不會(huì)跟其他shapeType屬性的值沖突即可。因此,這里就很適合改用 Symbol 值。
const shapeType = {
triangle: Symbol()
};最終的代碼
const shapeType = {
triangle: Symbol(),
circle: Symbol()
}
function getArea(shape) {
let area = 0
switch (shape) {
case shapeType.triangle:
area = .5 * options.width * options.height;
break;
case shapeType.circle:
// ... more code ...
break
}
return area
}
console.log(getArea(shapeType.triangle))Symbol 類型還可以用于定義一組常量,保證這組常量的值都是不相等的。
const COLOR_RED = Symbol();
const COLOR_GREEN = Symbol();
function getComplement(color) {
switch (color) {
case COLOR_RED:
return COLOR_GREEN;
case COLOR_GREEN:
return COLOR_RED;
default:
throw new Error('Undefined color');
}
}常量使用 Symbol 值最大的好處,就是其他任何值都不可能有相同的值了,因此可以保證上面的switch語句會(huì)按設(shè)計(jì)的方式工作。
Set
ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。
Set本身是一個(gè)構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu)。
let s = new Set() // 在實(shí)例化的同時(shí)傳入默認(rèn)的數(shù)據(jù)。 let s2 = new Set([1,2,3]) // 初始化的參數(shù)必須是可遍歷的,可以是數(shù)組或者自定義遍歷的數(shù)據(jù)結(jié)構(gòu)。
添加數(shù)據(jù)
let s = new Set()
s.add('chimmy')
s.add('18')
s.add('jimmy').add('18')
// Set 數(shù)據(jù)結(jié)構(gòu)不允許數(shù)據(jù)重復(fù),所以添加重復(fù)的數(shù)據(jù)是無效的
console.log(s); // Set(3) { 'chimmy', '18', 'jimmy' }刪除數(shù)據(jù)
// 刪除指定數(shù)據(jù)
s.delete('jimmy') // true
// 刪除全部數(shù)據(jù)
s.clear()查找和總數(shù)
// 判斷是否包含數(shù)據(jù)項(xiàng),返回 true 或 false
s.has('hello') // true
// 計(jì)算數(shù)據(jù)項(xiàng)總數(shù)
s.size // 3應(yīng)用場景
數(shù)組去重
let arr = [1, 2, 3, 4, 2, 3] let s = [...new Set(arr)] console.log(s) // [1,2,3,4]
合并去重
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])
console.log(s) // Set(6) { 1, 2, 3, 4, 5, 6 }
console.log([...s]) // [ 1, 2, 3, 4, 5, 6 ]
console.log(Array.from(s)) // [ 1, 2, 3, 4, 5, 6 ]交集
let arr1 = [1, 2, 3, 4] let arr2 = [2, 3, 4, 5, 6] let s1 = new Set(arr1) let s2 = new Set(arr2) let result = new Set(arr1.filter(item => s2.has(item))) console.log(Array.from(result)) // [ 2, 3, 4 ]
差集
let arr1 = [1, 2, 3, 4];
let arr2 = [2, 3, 4, 5, 6];
let s1 = new Set([1, 2, 3, 4])
let s2 = new Set([2, 3, 4, 5, 6])
let arr3 = new Set(arr1.filter(item => !s2.has(item)))
let arr4 = new Set(arr2.filter(item => !s1.has(item)))
console.log(arr3) // Set(1) { 1 }
console.log(arr4) // Set(2) { 5, 6 }
console.log([...arr3, ...arr4]) // [ 1, 5, 6 ]WeakSet
WeakSet 結(jié)構(gòu)與 Set 類似,也是不重復(fù)的值的集合。但是,它與 Set 有兩個(gè)區(qū)別。
WeakSet 的成員只能是對(duì)象,而不能是其他類型的值。
const ws = new WeakSet() ws.add(1) // TypeError: Invalid value used in weak set ws.add(Symbol()) // TypeError: invalid value used in weak set
let ws = new WeakSet()
const obj1 = {
name: 'imooc'
}
const obj2 = {
age: 5
}
ws.add(obj1)
ws.add(obj2)
ws.delete(obj1)
console.log(ws)
console.log(ws.has(obj2))WeakSet 沒有size屬性,沒有辦法遍歷它的成員。
WeakSet 中的對(duì)象都是弱引用,即垃圾回收機(jī)制不考慮 WeakSet 對(duì)該對(duì)象的引用,也就是說,如果其他對(duì)象都不再引用該對(duì)象,那么垃圾回收機(jī)制會(huì)自動(dòng)回收該對(duì)象所占用的內(nèi)存,不考慮該對(duì)象還存在于 WeakSet 之中。
Map
JavaScript 的對(duì)象(Object),本質(zhì)上是鍵值對(duì)的集合(Hash 結(jié)構(gòu)),但是傳統(tǒng)上只能用字符串當(dāng)作鍵。這給它的使用帶來了很大的限制。
const data = {};
const element = document.getElementById('myDiv');
data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata"上面代碼原意是將一個(gè) DOM 節(jié)點(diǎn)作為對(duì)象data的鍵,但是由于對(duì)象只接受字符串作為鍵名,所以element被自動(dòng)轉(zhuǎn)為字符串[object HTMLDivElement]。
為了解決這個(gè)問題,ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu)。它類似于對(duì)象,也是鍵值對(duì)的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對(duì)象)都可以當(dāng)作鍵。也就是說,Object 結(jié)構(gòu)提供了“字符串—值”的對(duì)應(yīng),Map 結(jié)構(gòu)提供了“值—值”的對(duì)應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實(shí)現(xiàn)。如果你需要“鍵值對(duì)”的數(shù)據(jù)結(jié)構(gòu),Map 比 Object 更合適。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false上面代碼使用 Map 結(jié)構(gòu)的set方法,將對(duì)象o當(dāng)作m的一個(gè)鍵,然后又使用get方法讀取這個(gè)鍵,接著使用delete方法刪除了這個(gè)鍵。
添加數(shù)據(jù)
let map = new Map()
let keyObj = {}
let keyFunc = function() {}
let keyString = 'a string'
// 添加鍵
map.set(keyString, "和鍵'a string'關(guān)聯(lián)的值")
map.set(keyObj, '和鍵keyObj關(guān)聯(lián)的值')
map.set(keyFunc, '和鍵keyFunc關(guān)聯(lián)的值')
console.log(map) //
// Map(3) {
// 'a string' => "和鍵'a string'關(guān)聯(lián)的值",
// {} => '和鍵keyObj關(guān)聯(lián)的值',
// [Function: keyFunc] => '和鍵keyFunc關(guān)聯(lián)的值'
// }刪除數(shù)據(jù)
// 刪除指定的數(shù)據(jù) map.delete(keyObj) // 刪除所有數(shù)據(jù) map.clear()
查找和統(tǒng)計(jì)
// 統(tǒng)計(jì)所有 key-value 的總數(shù) console.log(map.size) //3 // 判斷是否有 key-value console.log(map.has(keyObj)) // true
獲取
console.log(map.get(keyObj)) // 和鍵keyObj關(guān)聯(lián)的值
weakMap
WeakMap結(jié)構(gòu)與Map結(jié)構(gòu)類似,也是用于生成鍵值對(duì)的集合。
// WeakMap 可以使用 set 方法添加成員
const wm1 = new WeakMap()
const key = {
foo: 1
}
wm1.set(key, 2)
wm1.get(key) // 2
// WeakMap 也可以接受一個(gè)數(shù)組,
// 作為構(gòu)造函數(shù)的參數(shù)
const k1 = [1, 2, 3]
const k2 = [4, 5, 6]
const wm2 = new WeakMap([
[k1, 'foo'],
[k2, 'bar']
])
wm2.get(k2) // "bar"WeakMap與Map的區(qū)別有兩點(diǎn)。
- WeakMap的鍵名所指向的對(duì)象,不計(jì)入垃圾回收機(jī)制。
- WeakMap只接受對(duì)象作為鍵名(null除外),不接受其他類型的值作為鍵名。
const map = new WeakMap() map.set(1, 2) // TypeError: 1 is not an object! map.set(Symbol(), 2) // TypeError: Invalid value used as weak map key map.set(null, 2) // TypeError: Invalid value used as weak map key
最后
這篇文章已有萬字,受限于篇幅, ES6的Class,Proxy,Reflect,Promise,Module等自己后續(xù)會(huì)單獨(dú)寫幾篇文章,詳細(xì)講解。
推薦文章
到此這篇關(guān)于ES6語法大總結(jié)的文章就介紹到這了,更多相關(guān)ES6語法總結(jié)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)的白板效果(可以直接在網(wǎng)頁上寫字)
javascript動(dòng)畫系列之網(wǎng)頁白板 javascript實(shí)現(xiàn)的白板(兼容ff,ie,chrome,……)2010-07-07
HTML中使背景圖片自適應(yīng)瀏覽器大小實(shí)例詳解
這篇文章主要介紹了HTML中使背景圖片自適應(yīng)瀏覽器大小實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04
JS支持帶x身份證號(hào)碼驗(yàn)證函數(shù)
身份證號(hào)碼驗(yàn)證-支持新的帶x身份證2008-08-08
初學(xué)js插入節(jié)點(diǎn)appendChild insertBefore使用方法
由于可見insertBefore()方法的特性是在已有的子節(jié)點(diǎn)前面插入新的節(jié)點(diǎn)但是兩種情況結(jié)合起來發(fā)現(xiàn)insertBefore()方法插入節(jié)點(diǎn),是可以在子節(jié)點(diǎn)列表的任意位置。2011-07-07
setTimeout函數(shù)兼容各主流瀏覽器運(yùn)行執(zhí)行效果實(shí)例
setTimeout是一個(gè)很不錯(cuò)的函數(shù),網(wǎng)站頁面前端工程師經(jīng)常將其用于幾秒后執(zhí)行的動(dòng)作,下文要講的setTimeout可以很好地兼容IE6,7,8,9以及谷歌等主流瀏覽器2013-06-06
JavaScript實(shí)現(xiàn)旋轉(zhuǎn)輪播圖
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)旋轉(zhuǎn)輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
BootStrap Typeahead自動(dòng)補(bǔ)全插件實(shí)例代碼
本文給大家介紹BootStrap Typeahead自動(dòng)補(bǔ)全插件的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2016-08-08

