數(shù)組
ES6中對于數(shù)據(jù)做了進(jìn)一步的增強(qiáng),以便能夠更加方便地創(chuàng)建數(shù)組以及操作數(shù)組。
創(chuàng)建數(shù)組
Array.of
該方法用于將一組值轉(zhuǎn)換為數(shù)組。
Array.of(1); [1]
Array.of(3, 21, 22); [3,21,22]
這個(gè)方法的出現(xiàn)主要是為了彌補(bǔ)之前數(shù)組構(gòu)造函數(shù)的一些缺陷:
Arry(); // []
Array(3); // [undefined, undefined, undefined]
你會發(fā)現(xiàn)在使用單個(gè)數(shù)值參數(shù)的時(shí)候,那個(gè)參數(shù)被構(gòu)造器作為數(shù)組長度而進(jìn)行初始化。而兩個(gè)參數(shù)以上的時(shí)候,則返回由參數(shù)構(gòu)成的數(shù)組。而 Array.of() 方法總會創(chuàng)建一個(gè)包含所有傳入?yún)?shù)的數(shù)組,而不管參數(shù)的數(shù)量與類型。
Array.from
該方法通常用于將類似數(shù)組的對象以及可遍歷對象轉(zhuǎn)換成數(shù)組。你可以將NodeList,Set,Map等等解構(gòu)進(jìn)行數(shù)組的轉(zhuǎn)換。
利用該方法的第二個(gè)參數(shù),你可以指定一個(gè)回調(diào)函數(shù),用于對數(shù)組進(jìn)行映射操作。
//arguments為函數(shù)傳入的參數(shù)
let args = Array.from(arguments, value => value + 1);
//等同于
let args = Array.from(arguments).map(value => value + 1);
該方法的第三個(gè)參數(shù)是上下文,在映射函數(shù)中如果需要使用this,需要手動(dòng)傳入該參數(shù)。
在ES6中, Class 語法允許我們?yōu)閮?nèi)置類型(比如 Array)和自定義類新建子類(比如叫 SubArray)。這些子類也會繼承父類的靜態(tài)方法,比如 SubArray.from(),調(diào)用該方法后會返回子類 SubArray 的一個(gè)實(shí)例,而不是 Array 的實(shí)例。
實(shí)例方法
fill
fill() 方法能使用特定值填充數(shù)組中的一個(gè)或多個(gè)元素。
[1,2,3].fill(1); //用1填充數(shù)組所有項(xiàng) [1,1,1]
[1,2,3].fill(10, 2); //從索引2開始用10填充數(shù)組 [1, 2, 10]
[1,2,3,4].fill(0, 2, 3);//從索引2到索引3之間開始用0填充數(shù)組 [1,2,0,4]
find/findIndex
該方法的參數(shù)是一個(gè)回調(diào)函數(shù),用于查找數(shù)組中滿足回調(diào)函數(shù)測試的第一個(gè)值或者第一個(gè)索引(index)。
let numbers = [1,342,342,22, 34, 35];
console.log(numbers.find(n => n > 35)); // 342
console.log(numbers.findIndex(n => n > 33)); // 1
copyWithin
該方法用來復(fù)制自身元素,然后填充進(jìn)數(shù)組里。
補(bǔ)充
針對可迭代的對象,ES6提供了三個(gè)新的方法:entries,keys, values分別用于返回鍵值對、鍵名、鍵值的迭代器,可以使用for...of語法進(jìn)行訪問。而數(shù)組的鍵名其實(shí)就是它的索引值。
字符串
字符串的操作層面,ES6提供了模板對象、多行字符串的支持。
模板字面量
在ES6中,我們可以使用反引號(` )來包裹普通字符串。
在ES5,我們?nèi)绻梢粋€(gè)多行的字符串,通常要使用+連字符,而現(xiàn)在只要使用反引號就可以了。
var str = `Courses are provided in MOOC format with course material available online, mostly as videos complemented with exercise and example files.
All throughout the course, a technical expert will be available online to provide help and answer your questions.
Each course takes approximately 6 to 7 hours to complete, depending on your proficiency, and must be completed within one week.`;
另外,我們可以在字符串模板中制造替換位,從而使用一些變量來填充我們的模板。
var name = 'scq000';
var str = `Hello, ${name}`; // Hello,scq000
標(biāo)簽化模板
模板標(biāo)簽(template tag)能對模板字面量進(jìn)行轉(zhuǎn)換并返回最終的字符串值,標(biāo)簽在模板的起始處被指定。標(biāo)簽實(shí)際上就是一個(gè)函數(shù),它被調(diào)用時(shí)接收需要處理的模板字面量數(shù)據(jù),然后進(jìn)行處理后返回一個(gè)字符串。這個(gè)函數(shù)的第一個(gè)參數(shù)是一個(gè)數(shù)組,包含被JS解釋過的字面量字符串,隨后的參數(shù)是每個(gè)替換位的解釋值。
function tag(literals, ...substitutions) {
let result = '';
console.log(literals);
console.log(substitutions);
return result;
}
var name = 'scq000';
var age = 12;
let msg = tag`My name is ${name}, and my age is ${age}.`;
在上面這個(gè)例子中,literials被賦值為['My name is ', [, and my age is ], [.]],而substutions則是['scq000', 12],即用來替換的值。你可以在這個(gè)函數(shù)中,利用這兩個(gè)信息對字符串做進(jìn)一步的加工。
另外,有個(gè)內(nèi)置的String.raw標(biāo)簽,可以直接獲取模板字面量的原始值,即轉(zhuǎn)義之前的值。
let msg = String.raw`hello$1\nworld`;
console.log(msg); //hello$1\nworld
字符串實(shí)例方法
對于字符串的實(shí)例方法上,新增了一些比較常用的方法。
- includes: 在給定文本存在于字符串中的任意位置時(shí)會返回 true ,否則返回 false 。
- startsWith: 在給定文本出現(xiàn)在字符串起始處時(shí)返回 true ,否則返回 false 。
- endsWith: 在給定文本出現(xiàn)在字符串結(jié)尾處時(shí)返回 true ,否則返回 false 。
需要注意的是,與之前indexOf等方法不同,以上這些實(shí)例方法的參數(shù)不能傳入正則表達(dá)式,否則會拋出錯(cuò)誤。
- repeat: 接受一個(gè)參數(shù)作為字符串的重復(fù)次數(shù),返回一個(gè)將初始字符串重復(fù)指定次數(shù)的新字符串。
符號
從ES6開始,引入了第6個(gè)基本數(shù)據(jù)類型:符號(Symbol)。 它是一種特殊的、不可變的數(shù)據(jù)類型,可以作為對象屬性的標(biāo)識符使用。
創(chuàng)建符號值
const name = Symbol(); //注意這里不能用new,因?yàn)镾ymbol是基本數(shù)據(jù)類型
const aname = Symbol('aname'); //提供的這個(gè)參數(shù)主要用來調(diào)試
typeof name //"Symbol"
使用符號值
可以在任何能使用“計(jì)算屬性名”的場合使用符號。
let firstName = Symbol('first name');
let lastName = Symbol('last name');
let person = {
[firstName]: 'scq'
};
Object.defineProperty(person, firstName, { writable: false });
Object.defineProperties(person, {
[lastName]: {
value: '000',
writable: false
}
});
上面的例子,為person對象定義了兩個(gè)符號類型屬性,并將它們設(shè)為只讀的。利用這種方式,特別適合創(chuàng)建對象私有成員。
暴露內(nèi)部方法
利用Symbol的一些屬性,可以針對對象的一些內(nèi)部行為進(jìn)行操作。
- Symbol.iterator: 一個(gè)返回對象默認(rèn)迭代器的方法,使用for...of
- Symbol.match: 一個(gè)用于對字符串進(jìn)行匹配的方法,也用于確定一個(gè)對象是否可以作為正則表達(dá)式使用。使用String.prototype.match
- Symbol.replace:一個(gè)替換匹配字符串的子串的方法.使用String.prototype.replace
- Symbol.search
- Symbol.split
- Symbol.hasInstance: 一個(gè)確定一個(gè)構(gòu)造器對象識別的對象是否為它的實(shí)例的方法。使用 instanceof.
- Symbol.isConcatSpreadable: 一個(gè)布爾值,表明一個(gè)對象是否應(yīng)該flattened為它的數(shù)組元素。使用Array.prototype.concat().
- Symbol.unscopables: 擁有和繼承屬性名的一個(gè)對象的值被排除在與環(huán)境綁定的相關(guān)對象外。
- Symbol.species: 一個(gè)用于創(chuàng)建派生對象的構(gòu)造器函數(shù)。.
- Symbol.toPrimitive: 一個(gè)將對象轉(zhuǎn)化為基本數(shù)據(jù)類型的方法。
- Symbol.toStringTag: 用于對象的默認(rèn)描述的字符串值。使用Object.prototype.toString().
功能比較多,就不一一說明了。下面就以iterator來說明一下使用方法:
var iterator = {
[Symbol.iterator]() {
return {
start: 0,
next() {
if(this.start < 10) {
return {value: this.start ++, done: false}
}else {
return {value: undefined, done: true}
}
}
}
}
};
for(var value of iterator) {
console.log(vlaue);
}
上面的例子利用了Symbol.iterator這個(gè)屬性,使得對象iterator獲得了迭代器的能力。因此,可以對這個(gè)對象使用for...of的語法進(jìn)行迭代操作。
Set與Map
ES6中增加了兩個(gè)新的數(shù)據(jù)結(jié)構(gòu),Set和Map,補(bǔ)充了原本數(shù)組的一些不足之處。Set 是不包含重復(fù)值的列表,而Map 則是鍵與相對應(yīng)的值的集合。
Set
Set是一種無重復(fù)值的有序列表。
創(chuàng)建一個(gè)Set很簡單,只要使用new關(guān)鍵字就可以了。Set的構(gòu)造器實(shí)際上可以接受任何可迭代對象作為參數(shù)。在構(gòu)造器內(nèi)部,會使用迭代器來提取參數(shù)中的值。
let set1 = new Set(); //創(chuàng)建一個(gè)空的集合 Set {}
let set2 = new Set([1,2,3]); //創(chuàng)建一個(gè)包含三個(gè)元素的集合, Set {1, 2, 3}
let set3 = new Set([1,2,3,4,4]); //創(chuàng)建一個(gè)去重后的集合, Set {1, 2, 3}
針對Set,主要提供了以下幾個(gè)方法:
- add: 能向 Set 中添加項(xiàng)目
- has: 測試某個(gè)值是否存在于 Set 中
- delete: 來移除單個(gè)值
- clear: 來將所有值從 Set 中移除
還提供了一個(gè)size屬性用于判斷集合長度
let set = new Set([1,2,3,4,5,6]);
set.add(3); //由于3已經(jīng)在集合里了,并不會添加新項(xiàng)
set.add('nihao'); // Set {1,2,3,4,5,6,'nihao'}
set.has(3); //true
set.delete(3); // Set {1,2,4,5,6,'nihao'}
set.clear(); // Set {}
注意的是,當(dāng)一個(gè)屬性被添加到 set 對象時(shí),它的值也被設(shè)為true。而在 Set 內(nèi)部的比較使用了Object.is()方法,來判斷兩個(gè)值是否相等。
Set的遍歷
同數(shù)組一樣,作為可迭代的數(shù)據(jù)結(jié)構(gòu),ES6提供了forEach的方法對其進(jìn)行遍歷。你也可以使用,for...of的語法進(jìn)行。
let set = new Set(['a','b','c']);
set.forEach((value, key) => console.log('Value: ' + value + ' Key: ' + key));
//Value: a Key: a
//Value: b Key: b
//Value: c Key: c
由于Set的每一項(xiàng)同時(shí)被認(rèn)為鍵和值,因此,key和value其實(shí)是一致的。如果想在回調(diào)函數(shù)中使用 this ,你可以給 forEach() 傳入一個(gè) this 值作為第三個(gè)參數(shù)。你也可以使用箭頭函數(shù)來達(dá)到同等的效果。
轉(zhuǎn)換成數(shù)組
要將Set轉(zhuǎn)換成數(shù)組,可以像下面這樣:
let set = new Set([1,2,3,4,5]);
Array.from(set); //[1,2,3,4,5]
[...set]; //[1,2,3,4,5]
使用擴(kuò)展運(yùn)算符可以更簡單地將 Set 轉(zhuǎn)換回?cái)?shù)組。
Map
Map與Set相似,數(shù)據(jù)結(jié)構(gòu)中存儲著鍵值對。實(shí)例方法與Set相同的部分是has,delete,clear。你可以調(diào)用 set() 方法并給它傳遞一個(gè)鍵與一個(gè)關(guān)聯(lián)的值,來給 Map 添加項(xiàng);此后使用鍵名來調(diào)用 get() 方法便能提取對應(yīng)的值。
let map = new Map();
map.set('key1', 'value1'); //Map {"key1" => "value1"}
map.set('key2', 'value2'); //Map {"key1" => "value1", "key2" => "value2"}
map.get('key1'); //value1
map.has('key2'); //true
map.delete('key1'); //刪除成功會返回true
map.has('key1'); //false
map.clear(); //清空所有
而對于map的遍歷可以使用forEach語法,其中的回調(diào)函數(shù)同樣是接收三個(gè)參數(shù):value,key,context。當(dāng)然context是可選的。
let map = new Map();
map.set('key1', 'value1');
map.set('key2', 'value2');
map.forEach((value,key) => console.log(value));
//value1, value2
WeakSet和WeakMap
WeakMap和WeakSet一樣,存儲了是對象的弱引用方式。而Set和Weak的實(shí)例中,則是采用了強(qiáng)引用的方式,只要Set或Map的實(shí)例存在,其中所存儲的對象就無法被垃圾回收機(jī)制回收,從而無法釋放內(nèi)存。利用WeakSet和WeakMap的弱引用方式,則可以在內(nèi)存管理上有著更加容易優(yōu)化的空間。