Bable的Es6 2 Es5工具
let與const
let
let聲明的變量只在它所在的代碼塊有效。
{
let a = 10;
var b = 1;
}
a //Uncaught ReferenceError: a is not defined
b //1
let聲明的i只在for循環(huán)中有效
// let
for(let i=0;i<3;i++){} //let聲明的i只在for循環(huán)中有效
console.log(i); // ReferenceError: a is not defined
// var
for(var i=0;i<3;i++){} //for循環(huán)中的i是全局變量
console.log(i); //3 變量i只用來(lái)控制循環(huán),但是循環(huán)結(jié)束后,它并沒有消失,泄露成了全局變量。
// let
let a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
// var
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i); //i是全局變量
};
}
a[6](); // 10
// 改進(jìn)版 var
var a = [];
for (var i = 0; i < 10; i++) {
(function(j) { //用一個(gè)閉包把里面的i與
a[j] = function () {
console.log(j)
}
})(i) //每一次循環(huán)的i其實(shí)都是一個(gè)新的變量
}
a[6]();
for循環(huán)還特別之處,設(shè)置循環(huán)變量的那部分是一個(gè)父作用域,而循環(huán)體內(nèi)部是一個(gè)單獨(dú)的子作用域
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
let不存在變量提升
//let
console.log(bar); // 報(bào)錯(cuò)ReferenceError
let bar = 2;
//var
console.log(foo); // 輸出undefined
var foo = 2;
// var相當(dāng)于
var foo; //變量聲明默認(rèn)值為undefined
console.log(foo); // 輸出undefined
foo = 2; //先聲明再調(diào)用
“暫時(shí)性死區(qū)”(temporal dead zone,簡(jiǎn)稱 TDZ)
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
let不允許在相同作用域內(nèi),重復(fù)聲明同一個(gè)變量
let實(shí)際上為 JavaScript 新增了塊級(jí)作用域
ES5 只有全局作用域和函數(shù)作用域,沒有塊級(jí)作用域
// let
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5 外層代碼塊不受內(nèi)層代碼塊的影響
}
// var 10
// IIFE 寫法
(function () {
var tmp = ...;
...
}());
// 塊級(jí)作用域?qū)懛?{
let tmp = ...;
...
}
ES5 規(guī)定,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明,不能在塊級(jí)作用域聲明
應(yīng)該避免在塊級(jí)作用域內(nèi)聲明函數(shù)
const
const聲明一個(gè)只讀的常量
常量的值就不能改變
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const一旦聲明變量,就必須立即初始化,只聲明不賦值,就會(huì)報(bào)錯(cuò)。
const的作用域與let命令相同:只在聲明所在的塊級(jí)作用域內(nèi)有效。
const命令聲明的常量也不存在提升
const同樣存在暫時(shí)性死區(qū)
const只能在聲明后使用
const不可重復(fù)聲明
const實(shí)際上保證的,并不是變量的值不得改動(dòng),而是變量指向的那個(gè)內(nèi)存地址不得改動(dòng)。
變量的解構(gòu)賦值
數(shù)組解構(gòu)賦值
如果解構(gòu)不成功,變量的值就等于undefined
解構(gòu)賦值允許指定默認(rèn)值
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)算符(===),判斷一個(gè)位置是否有值。所以,只有當(dāng)一個(gè)數(shù)組成員嚴(yán)格等于undefined,默認(rèn)值才會(huì)生效
默認(rèn)值可以引用解構(gòu)賦值的其他變量,但該變量必須已經(jīng)聲明
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined
對(duì)象解構(gòu)賦值
數(shù)組的元素是按次序排列的,變量的取值由它的位置決定;而對(duì)象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值
如果變量名與屬性名不一致
let { foo} = { foo: 'aaa', bar: 'bbb' };
foo// "aaa"
let { foo:foo} = { foo: 'aaa', bar: 'bbb' };
foo// "aaa"
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
對(duì)象的解構(gòu)也可以指定默認(rèn)值
默認(rèn)值生效的條件是,對(duì)象的屬性值嚴(yán)格等于undefined
如果解構(gòu)失敗,變量的值等于undefined
如果要將一個(gè)已經(jīng)聲明的變量用于解構(gòu)賦值,會(huì)報(bào)錯(cuò),因?yàn)?JavaScript 引擎會(huì)將{x}理解成一個(gè)代碼塊
// 錯(cuò)誤的寫法
let x;
{x} = {x: 1}; // SyntaxError: syntax error
// 正確的寫法
let x;
({x} = {x: 1});
字符串解構(gòu)賦值
數(shù)值和布爾值解構(gòu)賦值
函數(shù)的參數(shù)解構(gòu)賦值
函數(shù)參數(shù)的解構(gòu)也可以使用默認(rèn)值
字符串的擴(kuò)展
字符的 Unicode
charCodeAt()
能夠正確處理 4 個(gè)字節(jié)儲(chǔ)存的字符,返回一個(gè)字符的碼點(diǎn)。
String.fromCodePoint()
字符串的遍歷
for (let codePoint of 'foo') {
console.log(codePoint)
}
// "f"
// "o"
// "o"
at()
normalize()
includes(),startsWith(),endsWith()
includes():返回布爾值,表示是否找到了參數(shù)字符串。
startsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的頭部。
endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部
repeat()
repeat方法返回一個(gè)新字符串,表示將原字符串重復(fù)n次
padStart(),padEnd()
padStart()用于頭部補(bǔ)全,padEnd()用于尾部補(bǔ)全
模板字符串
模板字符串(template string)是增強(qiáng)版的字符串,用反引號(hào)(`)標(biāo)識(shí)
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
// 字符串中嵌入變量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
使用模板字符串表示多行字符串,所有的空格和縮進(jìn)都會(huì)被保留在輸出之中,如果你不想要這個(gè)換行,可以使用trim方法消除它
標(biāo)簽?zāi)0?/h3>
String.raw()
正則的擴(kuò)展
數(shù)值的擴(kuò)展
二進(jìn)制和八進(jìn)制
Number.isFinite(),Number.isNaN()
只對(duì)數(shù)值有效
Number.parseInt(),Number.parseFloat()
Number.isInteger()
Number.isInteger()用來(lái)判斷一個(gè)數(shù)值是否為整數(shù)
由于 JavaScript 采用 IEEE 754 標(biāo)準(zhǔn),數(shù)值存儲(chǔ)為64位雙精度格式,數(shù)值精度最多可以達(dá)到 53 個(gè)二進(jìn)制位(1 個(gè)隱藏位與 52 個(gè)有效位)。如果數(shù)值的精度超過這個(gè)限度,第54位及后面的位就會(huì)被丟棄,這種情況下,Number.isInteger可能會(huì)誤判。
Number.EPSILON
極小的常量Number.EPSILON。根據(jù)規(guī)格,它表示 1 與大于 1 的最小浮點(diǎn)數(shù)之間的差
Number.EPSILON === Math.pow(2, -52)
0.1 + 0.2 === 0.3 // false
Number.isSafeInteger()
JavaScript 能夠準(zhǔn)確表示的整數(shù)范圍在-253到253之間(不含兩個(gè)端點(diǎn)),超過這個(gè)范圍,無(wú)法精確表示這個(gè)值,Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER這兩個(gè)常量,用來(lái)表示這個(gè)范圍的上下限,Number.isSafeInteger()則是用來(lái)判斷一個(gè)整數(shù)是否落在這個(gè)范圍之內(nèi)
Math.trunc()
Math.trunc方法用于去除一個(gè)數(shù)的小數(shù)部分,返回整數(shù)部分
Math.sign()
Math.sign方法用來(lái)判斷一個(gè)數(shù)到底是正數(shù)、負(fù)數(shù)、還是零。對(duì)于非數(shù)值,會(huì)先將其轉(zhuǎn)換為數(shù)值
Math.cbrt()
Math.cbrt方法用于計(jì)算一個(gè)數(shù)的立方根
指數(shù)運(yùn)算符(**)
2**2 //4
a **= 2; // 等同于 a = a * a;
函數(shù)的擴(kuò)展
ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面
function log(x, y = 'World') {
console.log(x, y);
}
參數(shù)變量是默認(rèn)聲明的,所以不能用let或const再次聲明
使用參數(shù)默認(rèn)值時(shí),函數(shù)不能有同名參數(shù)
參數(shù)默認(rèn)值不是傳值的,而是每次都重新計(jì)算默認(rèn)值表達(dá)式的值。也就是說,參數(shù)默認(rèn)值是惰性求值的
定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)
如果傳入undefined,將觸發(fā)該參數(shù)等于默認(rèn)值,null則沒有這個(gè)效果
函數(shù)的length屬性
函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個(gè)數(shù)。也就是說,指定了默認(rèn)值后,length屬性將失真
因?yàn)閘ength屬性的含義是,該函數(shù)預(yù)期傳入的參數(shù)個(gè)數(shù)。
作用域
參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域(context)。等到初始化結(jié)束,這個(gè)作用域就會(huì)消失。這種語(yǔ)法行為,在不設(shè)置參數(shù)默認(rèn)值時(shí),是不會(huì)出現(xiàn)的
參數(shù)默認(rèn)值設(shè)為undefined,表明這個(gè)參數(shù)是可以省略的
rest參數(shù)
用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了
rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。
arguments對(duì)象不是數(shù)組,而是一個(gè)類似數(shù)組的對(duì)象。所以為了使用數(shù)組的方法,必須使用Array.prototype.slice.call先將其轉(zhuǎn)為數(shù)組。rest 參數(shù)就不存在這個(gè)問題,它就是一個(gè)真正的數(shù)組
rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù)),否則會(huì)報(bào)錯(cuò)
函數(shù)的length屬性,不包括 rest 參數(shù)
name屬性
函數(shù)的name屬性,返回該函數(shù)的函數(shù)名。
bind返回的函數(shù),name屬性值會(huì)加上bound前綴
箭頭函數(shù)
使用一個(gè)圓括號(hào)代表參數(shù)部分
如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句,就要使用大括號(hào)將它們括起來(lái),并且使用return語(yǔ)句返回
由于大括號(hào)被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個(gè)對(duì)象,必須在對(duì)象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)
箭頭函數(shù)中的this
函數(shù)體內(nèi)的this對(duì)象,就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象。
箭頭函數(shù)中,this是固定的
this指向的固定化,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因?yàn)樗鼪]有this,所以也就不能用作構(gòu)造函數(shù)
箭頭函數(shù)嵌套
數(shù)組的擴(kuò)展
擴(kuò)展運(yùn)算符
擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...)。它好比 rest 參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列
console.log(...[1, 2, 3]) // 1 2 3
Array.from()
Array.from方法用于將兩類對(duì)象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對(duì)象(array-like object)和可遍歷(iterable)的對(duì)象
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']
Array.of()
Array.of方法用于將一組值,轉(zhuǎn)換為數(shù)組
數(shù)組實(shí)例的 copyWithin()
數(shù)組實(shí)例的 find() 和 findIndex()
數(shù)組實(shí)例的 fill()
fill方法使用給定值,填充一個(gè)數(shù)組
數(shù)組實(shí)例的 entries(),keys() 和 values()
數(shù)組實(shí)例的 includes()
Array.prototype.includes方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值
數(shù)組的空位
對(duì)象的擴(kuò)展
ES6 允許在對(duì)象之中,直接寫變量。這時(shí),屬性名為變量名, 屬性值為變量的值
屬性簡(jiǎn)寫
const foo = 'bar';
const baz = {foo}; // {foo: "bar"}
const baz = {foo: foo};
方法簡(jiǎn)寫
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
屬性名表達(dá)式
let obj = {
[lastWord]: 'world',
['h' + 'ello']() {
return 'hi';
}
};
const foo = 'bar';
const baz = { [foo]: 'abc'}; //{bar: "abc"}
const a={foo} //{foo: "bar"}
方法的 name 屬性
Object.is()
Object.assign()
屬性的可枚舉性和遍歷
Object.getOwnPropertyDescriptors()
super 關(guān)鍵字
關(guān)鍵字super,指向當(dāng)前對(duì)象的原型對(duì)象
super關(guān)鍵字表示原型對(duì)象時(shí),只能用在對(duì)象的方法之中,用在其他地方都會(huì)報(bào)錯(cuò)。
Object.keys(),Object.values(),Object.entries()
Symbol
作為屬性名的 Symbol
Symbol 值作為對(duì)象屬性名時(shí),不能用點(diǎn)運(yùn)算符
點(diǎn)運(yùn)算符后面總是字符串,所以不會(huì)讀取mySymbol作為標(biāo)識(shí)名所指代的那個(gè)值
使用 Symbol 值定義屬性時(shí),Symbol 值必須放在方括號(hào)之中。
Symbol.for(),Symbol.keyFor()
Set 和 Map 數(shù)據(jù)結(jié)構(gòu)
set
Set類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。
Set 本身是一個(gè)構(gòu)造函數(shù),用來(lái)生成 Set 數(shù)據(jù)結(jié)構(gòu)
WeakSet
WeakSet結(jié)構(gòu)與 Set 類似,也是不重復(fù)的值的集合。但是,它與 Set 有兩個(gè)區(qū)別。
首先,WeakSet 的成員只能是對(duì)象,而不能是其他類型的值