[TOC]
參考阮一峰的ECMAScript 6 入門
參考深入淺出ES6
let和const
- let和const都是用來聲明變量的,用法和var相似
- 用let或const定義的變量只能在let或const命令所在的代碼塊(塊級作用域)中有效
- es6中新增了塊級作用域
- ES6 允許塊級作用域的任意嵌套,如例2。
- 塊級作用域的出現(xiàn),實際上使得獲得廣泛應(yīng)用的立即執(zhí)行函數(shù)表達(dá)式(IIFE)不再必要了,如例3.
//例2
{{{{{let insane = 'Hello World'}}}}};
//外層作用域無法讀取內(nèi)層作用域的變量。
//內(nèi)層作用域可以定義外層作用域的同名變量。
//例3
// IIFE 寫法
(function () {
var tmp = ...;
...
}());
// 塊級作用域?qū)懛?{
let tmp = ...;
...
}
- 必須先聲明才能用,沒有預(yù)解釋,只要塊級作用域內(nèi)存在let命令,它所聲明的變量就“綁定”(binding)這個區(qū)域,不再受外部的影響。
未聲明就使用變量報錯的幾種情況
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上面的代碼會報錯,因為代碼塊中用let聲明了一個變量tmp,這個tmp就會跟代碼塊進(jìn)行綁定,而es6中規(guī)定,變量沒有聲明就使用就會報錯
// 報錯
let x = x;
// ReferenceError: x is not defined
變量x的聲明語句還沒有執(zhí)行完成前,就去取x的值,導(dǎo)致報錯”x 未定義“。
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 報錯
讓x=y,但是這時候y并沒有聲明就使用所以報錯
- let不允許在相同作用域內(nèi),重復(fù)聲明同一個變量。
// 報錯
function () {
let a = 10;
let a = 1;
}
// 以下兩行都會報錯
const message = "Goodbye!";
const age = 30;
//不允許在函數(shù)內(nèi)部重新聲明形參
function func(arg) {
let arg; // 報錯
}
function func(arg) {
{
let arg; // 不報錯
}
}
- let用于定義變量,const用于定義常量,const給一個變量賦值之后就不能給這個變量重新賦值,會報錯。
- 對于const來說,只聲明不賦值,就會報錯。
- const本質(zhì)上是保證變量所指向的內(nèi)存地址不改變,對于基本數(shù)據(jù)類型就是常量,對于引用數(shù)據(jù)類型,就是保證變量所對應(yīng)的內(nèi)存地址的指針不改變,但是里面的內(nèi)容無法保證;如果想讓對象的內(nèi)容也不能改變,應(yīng)該使用Object.freeze方法。
const foo = Object.freeze({});
// 常規(guī)模式時,下面一行不起作用;
// 嚴(yán)格模式時,該行會報錯
foo.prop = 123;
//除了將對象本身凍結(jié),對象的屬性也應(yīng)該凍結(jié)。下面是一個將對象徹底凍結(jié)的函數(shù)。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
- 在ES6中var和function聲明的全局變量,依舊是window的屬性;let、const、class聲明的全局變量,不屬于window的屬性。
- 在for循環(huán)中使用let聲明變量有一個特別之處,就是循環(huán)語句部分是一個父作用域,而循環(huán)體內(nèi)部是一個單獨(dú)的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代碼輸出了3次abc,這表明函數(shù)內(nèi)部的變量i和外部的變量i是分離的。
do表達(dá)式
{
let t = f();
t = t * t + 1;
}
上面代碼中,塊級作用域?qū)蓚€語句封裝在一起。但是,在塊級作用域以外,沒有辦法得到t的值,因為塊級作用域不返回值,除非t是全局變量。
要想得到塊級作用域中的返回值,可以在塊級作用域之前加上do,使它變成do表達(dá)式。
let x = do {
let t = f();
t * t + 1;
};
上面代碼中,變量x會得到整個塊級作用域的返回值。
關(guān)于ES6中的頂層對象
ES5中頂層對象不統(tǒng)一,瀏覽器下是window,node中是global
ES6中
- 全局環(huán)境中,this會返回頂層對象。但是,Node模塊和ES6模塊中,this返回的是當(dāng)前模塊。
- 函數(shù)里面的this,如果函數(shù)不是作為對象的方法運(yùn)行,而是單純作為函數(shù)運(yùn)行,this會指向頂層對象。但是,嚴(yán)格模式下,這時this會返回undefined。
- 不管是嚴(yán)格模式,還是普通模式,new Function('return this')(),總是會返回全局對象。但是,如果瀏覽器用了CSP(Content Security Policy,內(nèi)容安全政策),那么eval、new Function這些方法都可能無法使用。
變量的解構(gòu)賦值
解構(gòu)賦值的規(guī)則是,只要等號右邊的值不是對象或數(shù)組,就先將其轉(zhuǎn)為對象
數(shù)組的解構(gòu)賦值
只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值,如果解構(gòu)不成功,變量的值就等于undefined。
let [a, b, c] = [1, 2, 3];
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
- 解構(gòu)賦值允許指定默認(rèn)值,默認(rèn)值生效的條件是,解構(gòu)的值是undefined。
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
- ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷一個位置是否有值。所以,如果一個數(shù)組成員不嚴(yán)格等于undefined,默認(rèn)值是不會生效的。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
對象的解構(gòu)賦值
對象的解構(gòu)與數(shù)組有一個重要的不同。數(shù)組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
對象的解構(gòu)賦值是下面形式的簡寫,也就是說,對象的解構(gòu)賦值的內(nèi)部機(jī)制,是先找到同名屬性,然后再賦給對應(yīng)的變量。真正被賦值的是后者,而不是前者,前者只是要匹配的模式,后者才是變量。
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
使用對象的解構(gòu)賦值時,變量的聲明和賦值是一體的,對于let和const來說,變量不能重新聲明,所以一旦賦值的變量以前聲明過,就會報錯。
- 對象的解構(gòu)也可以指定默認(rèn)值,默認(rèn)值生效的條件是,對象的屬性值嚴(yán)格等于undefined。
var {x = 3} = {};
x // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
字符串的解構(gòu)賦值
字符串解構(gòu)賦值的時候會被轉(zhuǎn)成類數(shù)組
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
類似數(shù)組的對象都有一個length屬性,因此還可以對這個屬性解構(gòu)賦值。
let {length : len} = 'hello';
len // 5
Number和Boolean的解構(gòu)賦值
解構(gòu)賦值時,如果等號右邊是數(shù)值和布爾值,則會先轉(zhuǎn)為對象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
null和undefined的解構(gòu)賦值
由于undefined和null無法轉(zhuǎn)為對象,所以對它們進(jìn)行解構(gòu)賦值,都會報錯。
解構(gòu)賦值的用途
- 變量交換
let x = 1;
let y = 2;
[x, y] = [y, x];
- 取函數(shù)的返回值
// 返回一個數(shù)組
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一個對象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
- 提取JSON數(shù)據(jù)
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
- 函數(shù)參數(shù)的默認(rèn)值,不用再寫
var foo = config.foo || 'default foo'
;這樣的語句。
字符串的擴(kuò)展
includes、startsWith和endsWith
傳統(tǒng)上,JavaScript只有indexOf方法,可以用來確定一個字符串是否包含在另一個字符串中。ES6又提供了三種新方法。
- includes():返回布爾值,表示是否找到了參數(shù)字符串。
- startsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的頭部。
- endsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的尾部。
var s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
這三個方法都支持第二個參數(shù),表示開始搜索的位置
var s = 'Hello world!';
s.startsWith('world', 6) // true,第二個參數(shù)表示從索引n開始
s.endsWith('Hello', 5) // true,第二個參數(shù)表示前n個字符
s.includes('Hello', 6) // false,第二個參數(shù)表示從索引n開始
fo-of循環(huán)
for-of循環(huán)的功能
- for-of循環(huán)可以用來遍歷數(shù)組,for-in循環(huán)用來遍歷對象屬性。
for (var value of myArray) {
console.log(value);
}
- 這是最簡潔、最直接的遍歷數(shù)組元素的語法
- 這個方法避開了for-in循環(huán)的所有缺陷
- 與forEach()不同的是,它可以正確響應(yīng)break、continue和return語句
- for-of循環(huán)不僅支持?jǐn)?shù)組,還支持大多數(shù)類數(shù)組對象,例如DOM NodeList對象。
- for-of循環(huán)也支持字符串遍歷,它將字符串視為一系列的Unicode字符來進(jìn)行遍歷:
for (var chr of "") {
alert(chr);
}
repeat方法
repeat(n) n
是一個數(shù)字,表示將原字符串重復(fù)n次,返回一個新字符串
'x'.repeat(3) // "xxx"
參數(shù)如果是小數(shù),會被取整,如果repeat的參數(shù)是負(fù)數(shù)或者Infinity,會報錯。
'na'.repeat(2.9) // "nana"
如果參數(shù)是0到-1之間的小數(shù),則等同于0,這是因為會先進(jìn)行取整運(yùn)算。0到-1之間的小數(shù),取整以后等于-0,repeat視同為0。
'na'.repeat(-0.9) // ""
'na'.repeat(NaN) // ""
如果repeat的參數(shù)是字符串,則會先轉(zhuǎn)換成數(shù)字。
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"
padStart(),padEnd()
padStart()用于頭部補(bǔ)全,padEnd()用于尾部補(bǔ)全。一共接受兩個參數(shù),第一個參數(shù)用來指定字符串的最小長度,第二個參數(shù)是用來補(bǔ)全的字符串。如果省略第二個參數(shù),默認(rèn)使用空格補(bǔ)全長度。
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(4, 'ab') // 'xaba'
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
如果原字符串的長度,等于或大于指定的最小長度,則返回原字符串。
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
如果用來補(bǔ)全的字符串與原字符串,兩者的長度之和超過了指定的最小長度,則會截去超出位數(shù)的補(bǔ)全字符串。
'abc'.padStart(10, '0123456789')// '0123456abc'
模板字符串
模板字符串(template string)是增強(qiáng)版的字符串,用反引號``
標(biāo)識。它可以當(dāng)作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量,模板字符串中嵌入變量,需要將變量名寫在${}
之中。。
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
// 字符串中嵌入變量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
關(guān)于模板字符串嵌入變量
- 大括號內(nèi)部可以放入任意的JavaScript表達(dá)式,可以進(jìn)行運(yùn)算,以及引用對象屬性。
var x = 1;
var y = 2;
`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"
`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"
var obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// 3
- 模板字符串之中還能調(diào)用函數(shù)。
function fn() {
return "Hello World";
}
`foo ${fn()} bar`
// foo Hello World bar
如果大括號中的值不是字符串,將默認(rèn)調(diào)用toString方法轉(zhuǎn)換成字符串,如果模板字符串中的變量沒有聲明,將報錯。
- 標(biāo)簽?zāi)0?br> 模板字符串可以緊跟在一個函數(shù)名后面,該函數(shù)將被調(diào)用來處理這個模板字符串。這被稱為“標(biāo)簽?zāi)0濉惫δ埽╰agged template)。標(biāo)簽?zāi)0迤鋵嵅皇悄0澹呛瘮?shù)調(diào)用的一種特殊形式。“標(biāo)簽”指的就是函數(shù),緊跟在后面的模板字符串就是它的參數(shù)。
alert`123`
// 等同于
alert(123)
如果模板字符里面有變量,就不是簡單的調(diào)用了,而是會將模板字符串先處理成多個參數(shù),再調(diào)用函數(shù)。
var a = 5;
var b = 10;
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
tag函數(shù)的第一個參數(shù)是一個數(shù)組,數(shù)組項是模板字符串中那些沒有變量替換的部分,也就是說,變量替換只發(fā)生在數(shù)組各個項之間。
tag函數(shù)的其他參數(shù),都是模板字符串各個變量被替換后的值。由于本例中,模板字符串含有兩個變量,因此tag會接受到兩個參數(shù)。
tag函數(shù)所有參數(shù)的實際值如上面的代碼。
- String.raw函數(shù)
String.raw
方法,往往用來充當(dāng)模板字符串的處理函數(shù),返回一個斜杠都被轉(zhuǎn)義(即斜杠前面再加一個斜杠)的字符串,對應(yīng)于替換變量后的模板字符串。如果原字符串的斜杠已經(jīng)轉(zhuǎn)義,那么String.raw不會做任何處理。
String.raw`Hi\n${2+3}!`;
// "Hi\\n5!"
String.raw`Hi\u000A!`;
// 'Hi\\u000A!'
String.raw`Hi\\n`
// "Hi\\n"
正則表達(dá)式的擴(kuò)展
關(guān)于ES6中RegExp構(gòu)造函數(shù)
在ES6中RegExp構(gòu)造函數(shù)的第一個參數(shù)如果是一個正則表達(dá)式,可以使用第二個參數(shù)指定正則的的修飾符,在ES5中不可以,返回的正則表達(dá)式會忽略原有的正則表達(dá)式的修飾符,只使用新指定的修飾符。
new RegExp(/abc/ig, 'i')// /abc/i
關(guān)于字符串的正則方法
字符串對象共有4個方法,可以使用正則表達(dá)式:match()、replace()、search()和split()。
新增u修飾符
ES6對正則表達(dá)式添加了u修飾符,含義為“Unicode模式”,用來正確處理大于\uFFFF的Unicode字符。也就是說,會正確處理四個字節(jié)的UTF-16編碼。
Number的擴(kuò)展
二進(jìn)制和八進(jìn)制的新的寫法
ES6 提供了二進(jìn)制和八進(jìn)制數(shù)值的新的寫法,分別用前綴0b(或0B)和0o(或0O)表示。
**Number.isFinite(), Number.isNaN() **
ES6在Number對象上,新提供了Number.isFinite()和Number.isNaN()兩個方法。
Number.isFinite()用來檢查一個數(shù)值是否為有限的(finite)。
Number.isNaN()用來檢查一個值是否為NaN。
這兩個新方法只對數(shù)值有效,Number.isFinite()對于非數(shù)值一律返回false, Number.isNaN()只有對于NaN才返回true,非NaN一律返回false。
Number.parseInt(), Number.parseFloat()
ES6將全局方法parseInt()和parseFloat(),移植到Number對象上面,行為完全保持不變。
Number.isInteger()
Number.isInteger()用來判斷一個值是否為整數(shù)。
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("15") // false
Number.EPSILON
js中浮點數(shù)計算是不精確的(0.1+0.2)。ES6在Number對象上面,新增一個極小的常量Number.EPSILON,Number.EPSILON的實質(zhì)是一個可以接受的誤差范圍。為浮點數(shù)計算,設(shè)置一個誤差范圍.如果這個誤差能夠小于Number.EPSILON,我們就可以認(rèn)為得到了正確結(jié)果。
安全整數(shù)和Number.isSafeInteger()
JavaScript能夠準(zhǔn)確表示的整數(shù)范圍在-2^53(-2的53次方)
到2^53(2的53次方)
之間(不含兩個端點),超過這個范圍,無法精確表示這個值。
ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER這兩個常量,用來表示這個范圍的上下限。
Number.isSafeInteger()則是用來判斷一個整數(shù)是否落在這個范圍之內(nèi)。
Math對象的擴(kuò)展
ES6在Math對象上新增了17個與數(shù)學(xué)相關(guān)的方法。所有這些方法都是靜態(tài)方法,只能在Math對象上調(diào)用。
-
Math.trunc
方法用于去除一個數(shù)的小數(shù)部分,返回整數(shù)部分。對于非數(shù)值,Math.trunc內(nèi)部使用Number方法將其先轉(zhuǎn)為數(shù)值。對于空值和無法截取整數(shù)的值,返回NaN。
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc('123.456')// 123
Math.trunc(NaN); // NaN
Math.trunc('foo'); // NaN
Math.trunc(); // NaN
-
Math.sign
方法用來判斷一個數(shù)到底是正數(shù)、負(fù)數(shù)、還是零。它會返回五種值。
參數(shù)為正數(shù),返回+1;
參數(shù)為負(fù)數(shù),返回-1;
參數(shù)為0,返回0;
參數(shù)為-0,返回-0;
其他值,返回NaN。
-
Math.cbrt
方法用于計算一個數(shù)的立方根。對于非數(shù)值,Math.cbrt方法內(nèi)部也是先使用Number方法將其轉(zhuǎn)為數(shù)值。
Math.cbrt('8') // 2
Math.cbrt('hello') // NaN
Math.cbrt(1) // 1
Math.cbrt(2) // 1.2599210498948734
Math.clz32
方法返回一個數(shù)的32位無符號整數(shù)形式有多少個前導(dǎo)0。Math.imul
方法返回兩個數(shù)以32位帶符號整數(shù)形式相乘的結(jié)果,返回的也是一個32位的帶符號整數(shù)。Math.fround
方法返回一個數(shù)的單精度浮點數(shù)形式。Math.hypot
方法返回所有參數(shù)的平方和的平方根。Math.expm1(x)
返回ex - 1,即Math.exp(x) - 1。ath.log1p(x)
方法返回1 + x的自然對數(shù),即Math.log(1 + x)。如果x小于-1,返回NaN。Math.log10(x)
返回以10為底的x的對數(shù)。如果x小于0,則返回NaN。Math.log2(x)
返回以2為底的x的對數(shù)。如果x小于0,則返回NaN。Math.sinh(x)
返回x的雙曲正弦(hyperbolic sine)Math.cosh(x)
返回x的雙曲余弦(hyperbolic cosine)Math.tanh(x)
返回x的雙曲正切(hyperbolic tangent)Math.asinh(x)
返回x的反雙曲正弦(inverse hyperbolic sine)Math.acosh(x)
返回x的反雙曲余弦(inverse hyperbolic cosine)Math.atanh(x)
返回x的反雙曲正切(inverse hyperbolic tangent)Math.signbit()
方法判斷一個數(shù)的符號位是否設(shè)置了
如果參數(shù)是NaN,返回false
如果參數(shù)是-0,返回true
如果參數(shù)是負(fù)值,返回true
其他情況返回falseES2016 新增了一個指數(shù)運(yùn)算符(**)。指數(shù)運(yùn)算符可以與等號結(jié)合,形成一個新的賦值運(yùn)算符(**=)。
2 ** 2 // 4
2 ** 3 // 8
a **= 2;// 等同于 a = a * a;
數(shù)組的擴(kuò)展
-
Array.from
方法用于將兩類對象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對象(array-like object)和可遍歷(iterable)的對象(包括ES6新增的數(shù)據(jù)結(jié)構(gòu)Set和Map)。只要是部署了Iterator接口的數(shù)據(jù)結(jié)構(gòu),Array.from都能將其轉(zhuǎn)為數(shù)組。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES6的寫法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
-
Array.of
方法用于將一組值,轉(zhuǎn)換為數(shù)組。如果沒有參數(shù),就返回一個空數(shù)組。
Array.of(3, 11, 8) // [3,11,8]
- 數(shù)組實例的
copyWithin()
方法,將數(shù)組指定位置的成員復(fù)制到其他位置(會覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個方法,會修改當(dāng)前數(shù)組。
它接受三個參數(shù)。
target(必需):從該位置開始替換數(shù)據(jù)。
start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為0。如果為負(fù)值,表示倒數(shù)。
end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度。如果為負(fù)值,表示倒數(shù)。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
- 數(shù)組實例的find()和findIndex()
數(shù)組實例的find方法,用于找出第一個
符合條件的數(shù)組成員。它的參數(shù)是一個回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為true的成員,然后返回該成員。如果沒有符合條件的成員,則返回undefined。
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
上面代碼中,find方法的回調(diào)函數(shù)可以接受三個參數(shù),依次為當(dāng)前的值、當(dāng)前的位置和原數(shù)組。
數(shù)組實例的findIndex方法的用法與find方法非常類似,返回第一個符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。
- fill方法使用給定值,填充一個數(shù)組。用于初始化空數(shù)組,第二個和第三個參數(shù),用于指定填充的起始位置和結(jié)束位置。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
-
keys()
是對鍵名的遍歷,可以用for...of循環(huán)進(jìn)行遍歷 -
values()
是對鍵值的遍歷,可以用for...of循環(huán)進(jìn)行遍歷 -
entries()
是對鍵值對的遍歷,可以用for...of循環(huán)進(jìn)行遍歷 -
Array.prototype.includes
方法返回一個布爾值,表示某個數(shù)組是否包含給定的值,與字符串的includes方法類似。該方法屬于ES7,但Babel轉(zhuǎn)碼器已經(jīng)支持。
函數(shù)的擴(kuò)展
參數(shù)的默認(rèn)值
- 可以直接在函數(shù)的實參中設(shè)置函數(shù)的默認(rèn)值
function log(x, y = 'World') {
console.log(x, y);
}
- 參數(shù)變量是默認(rèn)聲明的,所以不能用let或const再次聲明。
- 使用參數(shù)默認(rèn)值時,函數(shù)不能有同名參數(shù)。
function foo(x, x, y = 1) {
// ...
}
// SyntaxError: Duplicate parameter name not allowed in this context
- 通常情況下,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)。因為這樣比較容易看出來,到底省略了哪些參數(shù)。如果非尾部的參數(shù)設(shè)置默認(rèn)值,實際上這個參數(shù)是沒法省略的。
- 指定了默認(rèn)值以后,函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個數(shù)。也就是說,指定了默認(rèn)值后,length屬性將失真。rest參數(shù)(可變參數(shù))也不會計入length屬性。
- 如果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù),那么length屬性也不再計入后面的參數(shù)了。
- 把參數(shù)的默認(rèn)值設(shè)成undefined表明這個參數(shù)是可以省略的
作用域
一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)執(zhí)行時,參數(shù)會形成一個單獨(dú)的作用域。等到執(zhí)行完,這個作用域就會消失。這種語法行為,在不設(shè)置參數(shù)默認(rèn)值時,是不會出現(xiàn)的。
rest參數(shù)
ES6 引入 rest 參數(shù)(形式為“...變量名”),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對象了。rest 參數(shù)是一個數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個參數(shù)),否則會報錯。
擴(kuò)展運(yùn)算符
- 擴(kuò)展運(yùn)算符(spread)是三個點(...)。它好比 rest 參數(shù)的逆運(yùn)算,將一個數(shù)組轉(zhuǎn)為用逗號分隔的參數(shù)序列。
任何Iterator接口的對象,都可以用擴(kuò)展運(yùn)算符轉(zhuǎn)為真正的數(shù)組。
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
該運(yùn)算符主要用于函數(shù)調(diào)用。
function add(x, y) {
return x + y;
}
var numbers = [4, 38];
add(...numbers) // 42
- 擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組。
[...'hello']
// [ "h", "e", "l", "l", "o" ]
- 函數(shù)的name屬性,返回該函數(shù)的函數(shù)名。如果將一個具名函數(shù)賦值給一個變量,則 ES5 和 ES6 的name屬性都返回這個具名函數(shù)原本的名字。
箭頭函數(shù)
- 基本用法
var f = () => 5;
var f = v => v;
var sum = (num1, num2) => num1 + num2;
- 如果箭頭函數(shù)的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
var sum = (num1, num2) => {
console.log(num1 + num2);
return num1 + num2;
}
- 由于大括號被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個對象,必須在對象外面加上括號
var getTempItem = id => ({ id: id, name: "Temp" });
箭頭函數(shù)的注意點
- 箭頭函數(shù)的this是他的父級的this,因為是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因為它沒有this,所以也就不能用作構(gòu)造函數(shù)。
- 不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用new命令,否則會拋出一個錯誤。
- 不可以使用arguments對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以用Rest參數(shù)代替。
- 不可以使用yield命令,因此箭頭函數(shù)不能用作Generator函數(shù)。
- 箭頭函數(shù)不存在arguments、super、new.target這三個變量。
- 箭頭函數(shù)不能用call()、apply()、bind()這些方法去改變this的指向。
函數(shù)綁定運(yùn)算符(::)
這是一個ES7的提案,但是babel已經(jīng)支持
雙冒號左邊是一個對象,右邊是一個函數(shù)。該運(yùn)算符會自動將左邊的對象,作為上下文環(huán)境(即this對象),綁定到右邊的函數(shù)上面。
foo::bar;
// 等同于
bar.bind(foo);
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;
對象的擴(kuò)展
屬性的簡潔寫法
ES6允許直接寫入變量和函數(shù),作為對象的屬性和方法。這樣的書寫更加簡潔,簡潔寫法的屬性名總是字符串,這會導(dǎo)致一些看上去比較奇怪的結(jié)果。
var obj = {
class () {}
};
// 等同于
var obj = {
'class': function() {}
};
var birth = '2000/01/01';
var Person = {
name: '張三',
//等同于birth: birth
birth,
// 等同于hello: function ()...
hello() { console.log('我的名字是', this.name); }
};
- ES6可以用下面這種方式定義對象
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
對象新增的方法
-
bject.is
是用來比較兩個值是否嚴(yán)格相等,與嚴(yán)格比較運(yùn)算符(===)的行為基本一致。不同之處只有兩個:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
- Object.assign方法用于對象的合并,將源對象(source)的所有可枚舉屬性,復(fù)制到目標(biāo)對象(target)。第一個參數(shù)是目標(biāo)對象,后面的參數(shù)都是源對象。
如果目標(biāo)對象與源對象有同名屬性,或多個源對象有同名屬性,則后面的屬性會覆蓋前面的屬性。
如果該參數(shù)不是對象,則會先轉(zhuǎn)成對象,然后返回。如果只有一個參數(shù),Object.assign會直接返回該參數(shù)。由于undefined和null無法轉(zhuǎn)成對象,所以如果它們作為參數(shù)并且是目標(biāo)對象(即第一個參數(shù)),就會報錯。
未完待續(xù)。。。
Symbol數(shù)據(jù)類型
ES5的對象屬性名都是字符串,這容易造成屬性名的沖突。ES6引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無二的值。它是JavaScript語言的第八種數(shù)據(jù)類型。
let s = Symbol();
typeof s// "symbol"
Symbol函數(shù)前不能使用new命令,否則會報錯。這是因為生成的Symbol是一個原始類型的值,不是對象。也就是說,由于Symbol值不是對象,所以不能添加屬性。基本上,它是一種類似于字符串的數(shù)據(jù)類型。
- Symbol函數(shù)可以接受一個字符串作為參數(shù),表示對Symbol實例的描述,主要是為了在控制臺顯示,或者轉(zhuǎn)為字符串時,比較容易區(qū)分。
Symbol函數(shù)的參數(shù)只是表示對當(dāng)前 Symbol 值的描述,因此相同參數(shù)的Symbol函數(shù)的返回值是不相等的。
// 沒有參數(shù)的情況
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false
// 有參數(shù)的情況
var s1 = Symbol('foo');
var s2 = Symbol('foo');
s1 === s2 // false
- 如果 Symbol 的參數(shù)是一個對象,就會調(diào)用該對象的toString方法,將其轉(zhuǎn)為字符串,然后才生成一個 Symbol 值。
- Symbol值不能與其他類型的值進(jìn)行運(yùn)算,會報錯。
- Symbol值能轉(zhuǎn)換成字符串和布爾值,但是不能轉(zhuǎn)換成數(shù)字。
- Symbol值可以用作對象的屬性名。Symbol值作為對象屬性名時,不能用點運(yùn)算符。
var mySymbol = Symbol();
var a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!
- 在對象的內(nèi)部,使用Symbol值定義屬性時,Symbol值必須放在方括號之中。
let s = Symbol();
let obj = {
[s]: function (arg) { ... }
};
obj[s](123);
上面代碼中,如果s不放在方括號中,該屬性的鍵名就是字符串s,而不是s所代表的那個Symbol值
- Symbol值作為屬性名時,該屬性是公有屬性,不是私有屬性。
- Symbol作為屬性名不可以被遍歷,可以使用Object.getOwnPropertySymbols方法獲得屬性名。
Symbol相關(guān)方法
- Symbol.for()
Symbol.for接受一個字符串作為參數(shù),搜索有沒有以該參數(shù)作為名稱的Symbol值。如果有,就返回這個Symbol值,否則就新建并返回一個以該字符串為名稱的Symbol值。Symbol.for會被登記在全局環(huán)境中供搜索
var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 // true
- Symbol.keyFor() 方法返回一個已登記的 Symbol 類型值的key。
就是前面已經(jīng)執(zhí)行過Symbol.for的
Symbol的內(nèi)置屬性
ES6提供了11個內(nèi)置的Symbol屬性,指向語言內(nèi)部使用的方法。
-
Symbol.hasInstance
屬性,指向一個內(nèi)部方法。當(dāng)其他對象使用instanceof運(yùn)算符,判斷是否為該對象的實例時,會調(diào)用這個方法。比如,foo instanceof Foo在語言內(nèi)部,實際調(diào)用的是Foo[Symbol.hasInstance](foo)。 -
Symbol.isConcatSpreadable
屬性等于一個布爾值,表示該對象使用Array.prototype.concat()時,是否可以展開。 -
Symbol.species
屬性,指向當(dāng)前對象的構(gòu)造函數(shù)。創(chuàng)造實例時,默認(rèn)會調(diào)用這個方法,即使用這個屬性返回的函數(shù)當(dāng)作構(gòu)造函數(shù),來創(chuàng)造新的實例對象 -
Symbol.match
屬性,指向一個函數(shù)。當(dāng)執(zhí)行str.match(myObject)時,如果該屬性存在,會調(diào)用它,返回該方法的返回值。 -
Symbol.replace
屬性,指向一個方法,當(dāng)該對象被String.prototype.replace方法調(diào)用時,會返回該方法的返回值。Symbol.replace方法會收到兩個參數(shù),第一個參數(shù)是replace方法正在作用的對象,第二個參數(shù)是替換后的值 -
Symbol.search
屬性,指向一個方法,當(dāng)該對象被String.prototype.search方法調(diào)用時,會返回該方法的返回值。 -
Symbol.split
屬性,指向一個方法,當(dāng)該對象被String.prototype.split方法調(diào)用時,會返回該方法的返回值。 -
Symbol.iterator
屬性,指向該對象的默認(rèn)遍歷器方法。 -
Symbol.toPrimitive
屬性,指向一個方法。該對象被轉(zhuǎn)為原始類型的值時,會調(diào)用這個方法,返回該對象對應(yīng)的原始類型值。 -
Symbol.toStringTag
屬性,指向一個方法。在該對象上面調(diào)用Object.prototype.toString方法時,如果這個屬性存在,它的返回值會出現(xiàn)在toString方法返回的字符串之中,表示對象的類型。也就是說,這個屬性可以用來定制[object Object]或[object Array]中object后面的那個字符串。 -
Symbol.unscopables
屬性,指向一個對象。該對象指定了使用with關(guān)鍵字時,哪些屬性會被with環(huán)境排除。
Set和Map數(shù)據(jù)結(jié)構(gòu)
Set
ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。
數(shù)組去重的新增2種寫法
// 數(shù)組去重
[...new Set(array)]
//數(shù)組去重
function dedupe(array) {
return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]) // [1, 2, 3]
Set相關(guān)的方法
- Set.prototype.constructor:構(gòu)造函數(shù),默認(rèn)就是Set函數(shù)。
- Set.prototype.size:返回Set實例的成員總數(shù)。
增刪改查
- add(value):添加某個值,返回Set結(jié)構(gòu)本身。
- delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
- has(value):返回一個布爾值,表示該值是否為Set的成員。
- clear():清除所有成員,沒有返回值。
遍歷
- keys():返回鍵名的遍歷器
- values():返回鍵值的遍歷器
- entries():返回鍵值對的遍歷器
- forEach():使用回調(diào)函數(shù)遍歷每個成員
WeakSet
WeakSet結(jié)構(gòu)與Set類似,也是不重復(fù)的值的集合。但是,它與Set有兩個區(qū)別。
- WeakSet的成員只能是對象,而不能是其他類型的值。
- WeakSet中的對象都是弱引用,即垃圾回收機(jī)制不考慮WeakSet對該對象的引用,也就是說,如果其他對象都不再引用該對象,那么垃圾回收機(jī)制會自動回收該對象所占用的內(nèi)存,不考慮該對象還存在于WeakSet之中。這個特點意味著,無法引用WeakSet的成員,因此WeakSet是不可遍歷的。
WeakSet相關(guān)方法
- WeakSet.prototype.add(value):向WeakSet實例添加一個新成員。
- WeakSet.prototype.delete(value):清除WeakSet實例的指定成員。
- WeakSet.prototype.has(value):返回一個布爾值,表示某個值是否在WeakSet實例之中。
Map
Map數(shù)據(jù)結(jié)構(gòu)類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當(dāng)作鍵。也就是說,Object結(jié)構(gòu)提供了“字符串—值”的對應(yīng),Map結(jié)構(gòu)提供了“值—值”的對應(yīng),是一種更完善的Hash結(jié)構(gòu)實現(xiàn)。如果你需要“鍵值對”的數(shù)據(jù)結(jié)構(gòu),Map比Object更合適。
只有對同一個對象的引用,Map結(jié)構(gòu)才將其視為同一個鍵。這一點要非常小心。
var map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
上面代碼的set和get方法,表面是針對同一個鍵,但實際上這是兩個值,內(nèi)存地址是不一樣的,因此get方法無法讀取該鍵,返回undefined。
Map相關(guān)屬性和方法
-
size
屬性返回Map結(jié)構(gòu)的成員總數(shù)。 -
set
方法設(shè)置key所對應(yīng)的鍵值,然后返回整個Map結(jié)構(gòu)。如果key已經(jīng)有值,則鍵值會被更新,否則就新生成該鍵。可以采用鏈?zhǔn)綄懛ā?/li> -
get
方法讀取key對應(yīng)的鍵值,如果找不到key,返回undefined。 -
has
方法返回一個布爾值,表示某個鍵是否在Map數(shù)據(jù)結(jié)構(gòu)中。 -
delete
方法刪除某個鍵,返回true。如果刪除失敗,返回false。 -
clear
方法清除所有成員,沒有返回值。 -
keys()
返回鍵名的遍歷器。 -
values()
返回鍵值的遍歷器。 -
entries()
返回所有成員的遍歷器。 -
forEach()
遍歷Map的所有成員。
Map與其他數(shù)據(jù)類型的轉(zhuǎn)換
- Map轉(zhuǎn)為數(shù)組
Map轉(zhuǎn)為數(shù)組最方便的方法,就是使用擴(kuò)展運(yùn)算符(...)。
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
- 數(shù)組轉(zhuǎn)為Map
將數(shù)組轉(zhuǎn)入Map構(gòu)造函數(shù),就可以轉(zhuǎn)為Map。
new Map([[true, 7], [{foo: 3}, ['abc']]])
// Map {true => 7, Object {foo: 3} => ['abc']}
- Map轉(zhuǎn)為對象
如果所有Map的鍵都是字符串,它可以轉(zhuǎn)為對象。
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
- 對象轉(zhuǎn)為Map
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({yes: true, no: false})
// [ [ 'yes', true ], [ 'no', false ] ]
- Map轉(zhuǎn)為JSON
Map轉(zhuǎn)為JSON要區(qū)分兩種情況。一種情況是,Map的鍵名都是字符串,這時可以選擇轉(zhuǎn)為對象JSON。
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
另一種情況是,Map的鍵名有非字符串,這時可以選擇轉(zhuǎn)為數(shù)組JSON。
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
- JSON轉(zhuǎn)為Map
JSON轉(zhuǎn)為Map,正常情況下,所有鍵名都是字符串。
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes":true,"no":false}')
// Map {'yes' => true, 'no' => false}
有一種特殊情況,整個JSON就是一個數(shù)組,且每個數(shù)組成員本身,又是一個有兩個成員的數(shù)組。這時,它可以一一對應(yīng)地轉(zhuǎn)為Map。這往往是數(shù)組轉(zhuǎn)為JSON的逆操作。
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}
WeakMap
WeakMap結(jié)構(gòu)與Map結(jié)構(gòu)基本類似,唯一的區(qū)別是它只接受對象作為鍵名(null除外),不接受其他類型的值作為鍵名,而且鍵名所指向的對象,不計入垃圾回收機(jī)制。
WeakMap只有四個方法可用:get()、set()、has()、delete()。
Proxy
待續(xù)……
Reflect
待續(xù)……
Promise 對象
Promise 的含義
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。ES6將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對象。
Promise,簡單說就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理。
Promise對象的特點
- 對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作,有三種狀態(tài):Pending(進(jìn)行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失敗)。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。
- 一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果。Promise對象的狀態(tài)改變,只有兩種可能:從Pending變?yōu)镽esolved和從Pending變?yōu)镽ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結(jié)果。如果改變已經(jīng)發(fā)生了,你再對Promise對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監(jiān)聽,是得不到結(jié)果的。
Promise的缺點
- 無法取消Promise,一旦新建它就會立即執(zhí)行,無法中途取消
- 如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯誤,不會反應(yīng)到外部
- 當(dāng)處于Pending狀態(tài)時,無法得知目前進(jìn)展到哪一個階段(剛剛開始還是即將完成)。
Promise的基本用法
Promise構(gòu)造函數(shù)接受一個函數(shù)作為參數(shù),該函數(shù)的兩個參數(shù)分別是resolve
和reject
,它們是兩個函數(shù)。
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
-
resolve
的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸腜ending變?yōu)镽esolved),在異步操作成功時調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去; -
reject
的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤笆 保磸腜ending變?yōu)镽ejected),在異步操作失敗時調(diào)用,并將異步操作報出的錯誤,作為參數(shù)傳遞出去。
Promise相關(guān)方法
-
then
方法可以分別指定當(dāng)promise的狀態(tài)是成功和失敗的時候的回調(diào)函數(shù)。then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以采用鏈?zhǔn)綄懛?/li>
promise.then(function(value) {
// 狀態(tài)成功的時候執(zhí)行的函數(shù)
}, function(error) {
// 狀態(tài)為失敗的時候執(zhí)行的函數(shù),這個函數(shù)可以省略
});
-
catch
相當(dāng)于.then(null, rejection),相當(dāng)于then方法的第二個參數(shù),一般用catch方法處理錯誤,不用then方法。
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 處理 getJSON 和 前一個回調(diào)函數(shù)運(yùn)行時發(fā)生的錯誤
console.log('發(fā)生錯誤!', error);
});
-
Promise.all
方法用于將多個Promise實例,包裝成一個新的Promise實例。
var p = Promise.all([p1, p2, p3]);
- 只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled,此時p1、p2、p3的返回值組成一個數(shù)組,傳遞給p的回調(diào)函數(shù)。
- 只要p1、p2、p3之中有一個被rejected,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調(diào)函數(shù)。
-
Promise.race
方法同樣是將多個Promise實例,包裝成一個新的Promise實例,只要p1、p2、p3之中有一個實例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調(diào)函數(shù)。
ES6的構(gòu)造函數(shù)和繼承
通過class來創(chuàng)建一個類,構(gòu)造函數(shù)寫在constructor里面
創(chuàng)建父類
class 類名{
constructor(param1,param2){
//私有的屬性和方法
}
getName(){
//公有的屬性和方法
}
static getAge(){
//類的靜態(tài)方法,也就是類的私有方法,實例不能使用
}
}
創(chuàng)建子類并繼承
class S extend F{
constructor(name,age,color){
super(name,age)//這句話必須要寫,寫了就是把父類的私有公有都繼承了過來
this.color=color//這樣給子類添加私有的
}
getSex(){
//這是子類公有的
}
}
Module的介紹
語法
// ES6模塊
import { stat, exists, readFile } from 'fs';
上面代碼的實質(zhì)是從fs模塊加載3個方法,其他方法不加載。
嚴(yán)格模式
ES6 的模塊自動采用嚴(yán)格模式,不管你有沒有在模塊頭部加上"use strict";。
ES6 模塊之中,頂層的this指向undefined,即不應(yīng)該在頂層代碼使用this。
模塊命令
模塊功能主要由兩個命令構(gòu)成:export和import。export命令用于規(guī)定模塊的對外接口,import命令用于輸入其他模塊提供的功能。import和export命令只能在模塊的頂層,不能在代碼塊之中,類似于全局作用域
export命令
export命令用于將模塊內(nèi)部的變量輸出到外面。
寫法
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
優(yōu)先采用下面這種寫法,export命令后面跟一個對象,對象里面是變量名
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
export輸出的變量就是本來的名字,但是可以使用as關(guān)鍵字重命名。
function v1() { ... }
export {
v1 as streamV1
};
ES6中不輸出任何接口的寫法
export {};//這個命令并不是輸出一個空對象,而是不輸出任何接口的 ES6 標(biāo)準(zhǔn)寫法。
import命令
import命令用于加載模塊
用法
import后面跟大括號,里面指定要從其他模塊導(dǎo)入的變量名。大括號里面的變量名,必須與被導(dǎo)入模塊對外接口的名稱相同。from
后面跟模塊的路徑,可以省略.js,如果不跟路徑,只寫模塊名,那么就必須要有配置文件來指定路徑
import {firstName, lastName, year} from './profile';
import命令也可以用as關(guān)鍵字重命名加載的變量;
import命令具有提升效果
,會提升到整個模塊的頭部,首先執(zhí)行。
import命令會執(zhí)行所加載的模塊;
import 'lodash';//只是執(zhí)行了模塊
整體加載模塊使用*
import * as circle from './circle';
export default 命令
export default 命令命令是默認(rèn)輸出的變量或函數(shù),當(dāng)其他模塊加載該模塊時,import命令可以為該匿名函數(shù)指定任意名字。注意,這時import命令后面,不使用大括號。
export 與 import 的復(fù)合寫法
如果在一個模塊之中,先輸入后輸出同一個模塊,import語句可以與export語句寫在一起。
export { foo, bar } from 'my_module';
// 等同于
import { foo, bar } from 'my_module';
export { foo, bar };
import函數(shù)
import函數(shù)是動態(tài)加載模塊,類似于node的require,區(qū)別主要是前者是異步加載,后者是同步加載。
import()返回一個 Promise 對象。后面可以跟then或catch方法
Module的加載實現(xiàn)
腳本的異步加載
在<script>標(biāo)簽中添加defer或async屬性,腳本就會異步加載。
<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
defer與async的區(qū)別
是:前者要等到整個頁面正常渲染結(jié)束,才會執(zhí)行;后者一旦下載完,渲染引擎就會中斷渲染,執(zhí)行這個腳本以后,再繼續(xù)渲染。一句話,defer是“渲染完再執(zhí)行”,async是“下載完就執(zhí)行”。另外,如果有多個defer腳本,會按照它們在頁面出現(xiàn)的順序加載,而多個async腳本是不能保證加載順序的。
ES6的編程規(guī)則
let和const之間應(yīng)該優(yōu)先使用const,所有的函數(shù)都應(yīng)該設(shè)置為常量
靜態(tài)字符串一律使用單引號或反引號,不使用雙引號。動態(tài)字符串使用反引號。
使用數(shù)組成員對變量賦值時,優(yōu)先使用解構(gòu)賦值。
函數(shù)的參數(shù)如果是對象的成員,優(yōu)先使用解構(gòu)賦值。
如果函數(shù)返回多個值,優(yōu)先使用對象的解構(gòu)賦值,而不是數(shù)組的解構(gòu)賦值。這樣便于以后添加返回值,以及更改返回值的順序。
單行定義的對象,最后一個成員不以逗號結(jié)尾。多行定義的對象,最后一個成員以逗號結(jié)尾。
// bad
const a = { k1: v1, k2: v2, };
const b = {
k1: v1,
k2: v2
};
// good
const a = { k1: v1, k2: v2 };
const b = {
k1: v1,
k2: v2,
};
對象盡量靜態(tài)化,一旦定義,就不得隨意添加新的屬性。如果添加屬性不可避免,要使用Object.assign方法。
對象的屬性和方法,盡量采用簡潔表達(dá)法,這樣易于描述和書寫。
var ref = 'some value';
// good
const atom = {
ref,
value: 1,
addValue(value) {
return atom.value + value;
},
};
使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組。
使用Array.from方法,將類似數(shù)組的對象轉(zhuǎn)為數(shù)組。
立即執(zhí)行函數(shù)可以寫成箭頭函數(shù)的形式。
(() => {
console.log('Welcome to the Internet.');
})();
那些需要使用函數(shù)表達(dá)式的場合,盡量用箭頭函數(shù)代替。因為這樣更簡潔,而且綁定了this。
簡單的、單行的、不會復(fù)用的函數(shù),建議采用箭頭函數(shù)。如果函數(shù)體較為復(fù)雜,行數(shù)較多,還是應(yīng)該采用傳統(tǒng)的函數(shù)寫法。
所有配置項都應(yīng)該集中在一個對象,放在最后一個參數(shù),布爾值不可以直接作為參數(shù)。
使用rest運(yùn)算符(...)代替arguments。因為rest運(yùn)算符顯式表明你想要獲取參數(shù),而且arguments是一個類似數(shù)組的對象,而rest運(yùn)算符可以提供一個真正的數(shù)組。
使用默認(rèn)值語法設(shè)置函數(shù)參數(shù)的默認(rèn)值。
注意區(qū)分Object和Map,只有模擬現(xiàn)實世界的實體對象時,才使用Object。如果只是需要key: value的數(shù)據(jù)結(jié)構(gòu),使用Map結(jié)構(gòu)。因為Map有內(nèi)建的遍歷機(jī)制。
用Class,取代需要prototype的操作。因為Class的寫法更簡潔,更易于理解。
使用extends實現(xiàn)繼承,因為這樣更簡單,不會有破壞instanceof運(yùn)算的危險。
Module語法是JavaScript模塊的標(biāo)準(zhǔn)寫法,堅持使用Module語法。使用import取代require。
使用export取代module.exports。
如果模塊只有一個輸出值,就使用export default,如果模塊有多個輸出值,就不使用export default,不要export default與普通的export同時使用。
不要在模塊輸入中使用通配符。因為這樣可以確保你的模塊之中,有一個默認(rèn)輸出(export default)。
如果模塊默認(rèn)輸出一個函數(shù),函數(shù)名的首字母應(yīng)該小寫。
如果模塊默認(rèn)輸出一個對象,對象名的首字母應(yīng)該大寫。
-
使用ESLint檢查語法規(guī)則和代碼風(fēng)格,保證寫出語法正確、風(fēng)格統(tǒng)一的代碼。
[ESLint的使用方式](http://es6.ruanyifeng.com/#docs/style)