簡介
相信大家都看過阮一峰老師的《ECMAScript6簡介》,博主也讀過很多次了,每次閱讀都有新的收穫,然後博主打算整理成一套完整筆記,做一套ES6總結系列。老話常說,讀書先把厚書讀薄,然後再把薄書讀厚,博主現在做的事是把書讀薄的過程,當然了,也是為了方便大家快速的瞭解ES6的特性以及本書的重要知識點,廢話不多說,直接開車。
第一章、EACMScript 6 簡介
1. EACMScript與JavaScript的關係
大家對JavaScript起源都有一定了解,這個就不再贅述,直接引用ES6的總結:
ECMAScript 和 JavaScript 的關係是,前者是後者的規格,後者是前者的一種實現。
另外的 ECMAScript 方言還有 JScript 和ActionScript。日常場合,這兩個詞是可以互換的。
複製程式碼
2. Babel 轉碼器
- Babel的作用
- 1.1 Babel babeljs.io/ 是一個廣泛使用的 ES6 轉碼器,可以將 ES6 程式碼轉為 ES5 程式碼,從而在老版本的瀏覽器執行
// 轉碼前
input.map(item => item + 1);
// 轉碼後
input.map(function (item) {
return item + 1;
});
複製程式碼
由於ES6有相容性問題,導致有些語法糖不能在某些瀏覽器上正確執行,經過Babel轉碼之後變成大家都相容的ES5,就可以正常執行了。
- 安裝以及配置
- 2.2.1 在專案的命令列安裝
$ npm install --save-dev @babel/core
- 2.2.2 .babelrc檔案用來設定轉碼規則和外掛,基本規格如下:
{
"presets": [
"@babel/env", //最新轉碼規則
"@babel/preset-react" //react 轉碼規則
],
"plugins": []
}
複製程式碼
presets欄位設定轉碼規則: 官方提供以下的規則集(需要先安裝再在**.babelrc檔案**中使用,安裝如下)
# 最新轉碼規則
$ npm install --save-dev @babel/preset-env
# react 轉碼規則
$ npm install --save-dev @babel/preset-reac
複製程式碼
注意,以下所有 Babel 工具和模組的使用,都必須先寫好.babelrc。
- 2.2.3 命令列工具@babel/cli、@babel/node、@babel/register 它的安裝命令如下:
$ npm install --save-dev @babel/cli
$ npm install --save-dev @babel/node #提供一個支援 ES6 的 REPL 環境
$ npm install --save-dev @babel/register
#改寫require命令,為它加上一個鉤子。
#每當使用require載入.js、.jsx、.es和.es6
#字尾名的檔案,就會先用 Babel 進行轉碼
複製程式碼
@babel/cli 基本用法(babel指令):
# 轉碼結果輸出到標準輸出
$ npx babel example.js
# 轉碼結果寫入一個檔案
# --out-file 或 -o 引數指定輸出檔案
$ npx babel example.js --out-file compiled.js
# 或者
$ npx babel example.js -o compiled.js
# 整個目錄轉碼
# --out-dir 或 -d 引數指定輸出目錄
$ npx babel src --out-dir lib
# 或者
$ npx babel src -d lib
# -s 引數生成source map檔案
$ npx babel src -d lib -s
複製程式碼
@babel/node 基本用法(babel-node指令)
$ npx babel-node
> (x => x * 2)(1)
2
複製程式碼
@babel/register 基本用法
//使用時必須首先載入@babel/register
require('@babel/register');
require('./es6.js');
複製程式碼
- 2.2.4 polyfill (用來轉換babel無法轉換的API以及一些語法) 使用core-js和regenerator-runtime(提供generator函式的轉碼)。
- 安裝:
$ npm install --save-dev core-js regenerator-runtime
- 使用
import 'core-js';
import 'regenerator-runtime/runtime';
// 或者
require('core-js');
require('regenerator-runtime/runtime);
複製程式碼
Babel 預設不轉碼的 API 非常多,詳細清單可以檢視babel-plugin-transform-runtime模組的github.com/babel/babel…檔案
- 瀏覽器環境
- Babel 也可以用於瀏覽器環境,使用@babel/standalone模組提供的瀏覽器版本,將其插入網頁。
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// Your ES6 code
</script>
複製程式碼
注意,網頁實時將 ES6 程式碼轉為 ES5,對效能會有影響。生產環境需要載入已經轉碼完成的指令碼。
Babel 提供一個REPL 線上編譯器,可以線上將 ES6 程式碼轉為 ES5 程式碼。轉換後的程式碼,可以直接作為 ES5 程式碼插入網頁執行。
第二章、let 和 const 命令
1. let 的特性以及用法
- 首先,我先總結一下var缺點
- 1.1 允許重複的變數宣告:導致資料被覆蓋
- 1.2 變數提升:怪異的資料訪問、閉包問題
- 1.3 全域性變數掛載到全域性物件:全域性物件成員汙染問題
// 1. 允許重複的變數宣告:導致資料被覆蓋
var a = 1;
function print(){
console.log(a)
}
// 假設這裡有一千行程式碼
var a = 2;
print(); // 2
// 2. 變數提升:怪異的資料訪問
if (Math.random() < 0.5) {
var a = "abc";
console.log(a);
}
else {
console.log(a);
}
console.log(a); // 無論怎樣訪問都是abc
// 3. 全域性變數掛載到全域性物件:全域性物件成員汙染問題
var abc = "123";
console.log(window.abc); // 123
// var console = "abc";
// console.log(console) // abc 這個很可怕
複製程式碼
- let (完美的解決了這些問題)
- let宣告的變數不會掛載到全域性物件
- let宣告的變數,不允許當前作用域範圍內重複宣告
- 使用let不會有變數提升,因此,不能在定義let變數之前使用它(形成暫時性死區)
- 暫時性死區:在程式碼塊內,使用let命令宣告變數之前,該變數都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。
- 塊級作用域:程式碼執行時遇到花括號,會建立一個塊級作用域,花括號結束,銷燬塊級作用域
// 1. let宣告的變數不會掛載到全域性物件
let a = 123;
console.log(window.a) // undefined
// 2. let宣告的變數,不允許當前作用域範圍內重複宣告
if (Math.random() < 0.5) {
let a = 123; //定義在當前塊級作用域
console.log(a) //當前塊級作用域中的a
} else {
//這是另外一個塊級作用域,該作用域中找不到a
console.log(a)
}
//3. 使用let不會有變數提升,因此,不能在定義let變數之前使用它
console(c); // Uncaught ReferenceError: c is not defined 形成了暫時性死區
let c = 6;
複製程式碼
暫時性死區的本質就是,只要一進入當前作用域,所要使用的變數就已經存在了,但是不可獲取,只有等到宣告變數的那一行程式碼出現,才可以獲取和使用該變數。
2. const 特性以及方法
- const和let完全相同,僅在於用const宣告的變數,必須在宣告時賦值,而且不可以重新賦值。(這裡就不再舉例其使用了)
- 實際上,在開發中,應該儘量使用const來宣告變數,以保證變數的值不會隨意篡改,原因:
- 根據經驗,開發中的很多變數,都是不會更改,也不應該更改的。
- 後續的很多框架或者是第三方JS庫,都要求資料不可變,使用常量可以一定程度上保證這一點。
注意
- 常量不可變,是指宣告的常量的記憶體空間不可變,並不保證記憶體空間中的地址指向的其他空間不可變
- 常量的命名
- 特殊的常量:該常量從字面意義上,一定是不可變的,比如圓周率、月地距地或其他一些絕不可能變化的配置。通常,該常量的名稱全部使用大寫,多個單詞之間用下劃線分割
- 普通的常量:使用和之前一樣的命名即可
- 在for迴圈中,迴圈變數不可以使用常量,只能用let 關於主義的第一點,我舉個例子
const a = {
name: "kevin",
age: 123
};
a.name = "abc";
console.log(a) // abc
// const PI = 3.14;
// const MOON_EARTH_DISTANCE = 3245563424; //月地距離
複製程式碼
3. 頂層物件屬性
- 頂層物件,在瀏覽器環境指的是window物件,在 Node 指的是global物件
var a = 1;
// 如果在 Node 的 REPL 環境,可以寫成 global.a
// 或者採用通用方法,寫成 this.a
window.a // 1
let b = 1;
window.b // undefined let命令、const命令、class命令宣告的全域性變數,不屬於頂層物件的屬性
複製程式碼
- globalThis 物件
因為環境的不同,頂層物件在各種實現裡面是不統一的
- 瀏覽器裡面,頂層物件是window,但 Node 和 Web Worker 沒有window。
- 瀏覽器和 Web Worker 裡面,self也指向頂層物件,但是 Node 沒有self。
- Node 裡面,頂層物件是global,但其他環境都不支援。 在不同環境中獲取頂層物件的this ES6 提供了兩個方法
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
複製程式碼
而且,ES6最後提到:
- ES2020 在語言標準的層面,引入globalThis作為頂層物件。也就是說,任何環境下,globalThis都是存在的,都可以從它拿到頂層物件,指向全域性環境下的this。
- 墊片庫global-this模擬了這個提案,可以在所有環境拿到globalThis。
第三章、變數的解構賦值
- 在此,我這裡主要介紹工作中我們常用的幾種解構賦值:
- 物件的結構
- 陣列的結構
- 引數的結構
- 其他的結構
1. 物件的結構
1. 什麼是解構
- ES6 允許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這被稱為解構(Destructuring) 解構不會對被解構的目標造成任何影響
- 在解構中使用預設值
{同名變數 = 預設值}
const user = {
name: "kevin",
age: 11,
sex: "男",
address: {
province: "四川",
city: "成都"
}
}
//解構出user中的name、province
//定義兩個變數name、province
//再解構
const { name, address: { province } } = user;
console.log(name, province)
// name: kevin province: 四川
複製程式碼
- 非同名屬性解構
{屬性名:變數名}
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]
//如果解構模式是巢狀的物件,而且子物件所在的父屬性不存在,那麼將會報錯
let {foo: {bar}} = {baz: 'baz'};
// 報錯
複製程式碼
2. 陣列的結構
let [a, b, c] = [1, 2, 3];
// a:1 b:2 c:3
複製程式碼
這種寫法屬於模式匹配,只要等號兩邊的模式相同,左邊的變數就會被賦予對應的值
- 下面一些使用巢狀陣列進行解構的例子以及一些情況
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1 bar // 2 baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
// 1. 不完全解構,即等號左邊的模式,只匹配一部分的等號右邊的陣列。這種情況下,解構依然可以成功。
let [x, y] = [1, 2, 3];
x // 1 y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1 b // 2 d // 4
// 2. 陣列解構出 值和陣列(運用擴充套件運算子... 在接下來的章節裡會就介紹到)
let [head, ...tail] = [1, 2, 3, 4];
head // 1 tail // [2, 3, 4]
// 3. 如果解構不成功,變數的值就等於undefined。
let [x, y, ...z] = ['a'];
x // "a" y // undefined z // []
// 4. 如果等號的右邊不是陣列(或者嚴格地說,不是可遍歷的結構,參見《Iterator》一章),那麼將會報錯。
// 4.1 要麼轉為物件以後不具備 Iterator 介面
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
// 4.2 本身就不具備 Iterator 介面
let [foo] = {};
複製程式碼
從最後的例子可以看出,只要某種資料結構具有 Iterator 介面,都可以採用陣列形式的解構賦值。
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
複製程式碼
上面程式碼中,fibs是一個 Generator 函式(參見《Generator 函式》一章),原生具有 Iterator 介面。解構賦值會依次從這個介面獲取值。
3. 引數的結構
廢話不多說,直接上例子
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
// 函式add的參數列面上是一個陣列,但在傳入引數的那一刻,陣列引數就被解構成變數x和y。
// 對於函式內部的程式碼來說,它們能感受到的引數就是x和y。
複製程式碼
箭頭函式也可以解構賦值
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
複製程式碼
函式引數的解構也可以使用預設值 在第五章會給出介紹
function move({x = 0, y = 0} = {}) { //x y 在引數上設定預設值
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
// 函式move的引數是一個物件,通過對這個物件進行解構,得到變數x和y的值。
// 如果解構失敗,x和y等於預設值。
複製程式碼
undefined就會觸發函式引數的預設值。
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
複製程式碼
4. 其他的解構
- 物件的解構也可以指定預設值 設定預設值
var {x = 3} = {};
x // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
var {x: y = 3} = {};
y // 3
var {x: y = 3} = {x: 5};
y // 5
var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong"
複製程式碼
- 預設值生效的條件是,物件的屬性值嚴格等於undefined。
var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null 因為null與undefined不嚴格相等,所以是個有效的賦值,導致預設值3不會生效
複製程式碼
注意點
- 如果要將一個已經宣告的變數用於解構賦值,必須非常小心。
// 錯誤的寫法
let x;
{x} = {x: 1};
// SyntaxError: syntax error因為JavaScript引擎會將{x}理解成一個程式碼塊,從而發生語法錯誤。
// 只有不將大括號寫在行首,避免 JavaScript 將其解釋為程式碼塊,才能解決這個問題。
// 正確的寫法
let x;
({x} = {x: 1});
複製程式碼
- 解構賦值允許等號左邊的模式之中,不放置任何變數名。因此,可以寫出非常古怪的賦值表示式
({} = [true, false]);
({} = 'abc');
({} = []);
複製程式碼
- 由於陣列本質是特殊的物件,因此可以對陣列進行物件屬性的解構。
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
複製程式碼
第四章、字串的擴充套件
1. 更好的Unicode支援
首先,介紹一下碼元:
- 早期,由於儲存空間寶貴,Unicode使用16位二進位制來儲存文字。我們將一個16位的二進位制編碼叫做一個碼元(Code Unit)。後來,由於技術的發展,Unicode對文字編碼進行了擴充套件,將某些文字擴充套件到了32位(佔用兩個碼元),並且,將某個文字對應的二進位制數字叫做碼點(Code Point)。
ES6為了解決這個困擾,為字串提供了方法:codePointAt,根據字串碼元的位置得到其碼點。
同時,ES6為正規表示式新增了一個flag: u,如果新增了該配置,則匹配時,使用碼點匹配
const text = "?"; //佔用了兩個碼元(32位)
console.log("字串長度:", text.length); // 2
console.log("使用正則測試:", /^.$/u.test(text)); // true
console.log("得到第一個碼元:", text.charCodeAt(0)); // 55362
console.log("得到第二個碼元:", text.charCodeAt(1)); // 57271
//?:\ud842\udfb7
console.log("得到第一個碼點:", text.codePointAt(0)); // 134071
console.log("得到第二個碼點:", text.codePointAt(1)); // 57271
複製程式碼
然後我們完成一個自己的判斷字串char,是32位,還是16位方法
function is32bit(char, i) {
//如果碼點大於了16位二進位制的最大值,則其是32位的
return char.codePointAt(i) > 0xffff;
}
複製程式碼
得到一個字串碼點的真實長度
function getLengthOfCodePoint(str) {
var len = 0;
for (let i = 0; i < str.length; i++) {
//i在索引碼元
if (is32bit(str, i)) {
//當前字串,在i這個位置,佔用了兩個碼元
i++;
}
len++;
}
return len;
}
console.log("?是否是32位的:", is32bit("?", 0)) // ?是否是32位的: true
console.log("ab?ab的碼點長度:", getLengthOfCodePoint("ab?ab")) // ab?ab的碼點長度: 5
複製程式碼
2. 增加的字串API(只舉出工作中常用的四種)
- includes 判斷字串中是否包含指定的子字串
- startsWith 判斷字串中是否以指定的字串開始
- endsWith 判斷字串中是否以指定的字串結尾
- repeat 將字串重複指定的次數,然後返回一個新字串
const text = "我真是狠人";
console.log("是否包含“狠”:", text.includes("狠"));
console.log("是否以“我”開頭:", text.startsWith("我"));
console.log("是否以“狠人”結尾:",
text.endsWith("狠人"));
console.log("重複4次:", text.repeat(4));
// 由於過於簡單,就不把console結果展示啦,有興趣的可以直接試一下,哈哈哈
複製程式碼
3. 模板字串
模板字串是此章節的靈魂
- ES6之前處理字串繁瑣的兩個方面:
- 多行字串
- 字串拼接
- 在ES6中,提供了模板字串的書寫,可以非常方便的換行和拼接,要做的,僅僅是將字串的開始或結尾改為 ` 符號
如果要在字串中拼接js表示式,只需要在模板字串中使用${JS表示式}
var love1 = "秋葵";
var love2 = "香菜";
var text = `A喜歡${love1}
B也喜歡${love2}
表示式可以是任何有意義的資料${1 + 3 * 2 / 0.5}
表示式是可以巢狀的:${`表示式中的模板字串${love1 + love2}`}
\n\n
奧布瓦的發順豐
在模板字串中使用\${JS表示式}可以進行插值
`;
console.log(text);
複製程式碼
在模板字串書寫之前,可以加上標記:
標記名`模板字串`
複製程式碼
標記是一個函式,函式引數如下:
- 引數1:被插值分割的字串陣列
- 後續引數:所有的插值
var love1 = "秋葵";
var love2 = "香菜";
var text = myTag`鄧哥喜歡${love1},鄧哥也喜歡${love2}。`;
//相當於:
// text = myTag(["A喜歡", ",B也喜歡", "。"], "秋葵", "香菜")
function myTag(parts) {
const values = Array.prototype.slice.apply(arguments).slice(1);
let str = "";
for (let i = 0; i < values.length; i++) {
str += `${parts[i]}:${values[i]}`;
if (i === values.length - 1) {
str += parts[i + 1];
}
}
return str;
}
console.log(text); //A喜歡:秋葵,B也喜歡:香菜
複製程式碼
第五章、函式的擴充套件
1. 在書寫形參時,直接給形參賦值,附的值即為預設值(在解構的時候有過應用)
這樣一來,當呼叫函式時,如果沒有給對應的引數賦值(給它的值是undefined),則會自動使用預設值
- 留意暫時性死區 形參
- 和ES6中的let或const宣告一樣,具有作用域,並且根據引數的宣告順序,存在暫時性死區。
- 對arguments的影響
-
只要給函式加上引數預設值,該函式會自動變數嚴格模式下的規則:arguments和形參脫離
-
暫時性死區
function test(a = b, b) {
console.log(a, b);
}
test(undefined, 2);// 報錯 因為傳a值undefined, 然後會給a賦預設值 b ,但是此時 b還沒有賦值,所以報錯。在上邊解構賦值中也介紹過
function sum(a, b = 1, c = 2) {
return a + b + c;
}
console.log(sum(10, undefined, undefined))
console.log(sum(11))
console.log(sum(1, undefined, 5)) // 這種情況才是正常
複製程式碼
- 對arguments的影響
function test(a, b = 1) {
console.log("arugments", arguments[0], arguments[1]); //arugments 1 2
console.log("a:", a, "b:", b); //a: 1 b: 2
a = 3;
console.log("arugments", arguments[0], arguments[1]); //arugments 1 2
console.log("a:", a, "b:", b); //a: 3 b: 2
}
test(1, 2);
複製程式碼
ES6的剩餘引數專門用於手機末尾的所有引數,將其放置到一個形引數組中。語法:
function (...形參名){
}
複製程式碼
注意:
- 一個函式,僅能出現一個剩餘引數
- 一個函式,如果有剩餘引數,剩餘引數必須是最後一個引數
function test(a, b, ...args) {
console.log(a, b, args);
}
test(1, 32, 46, 7, 34); //1 32 [46, 7, 34]
複製程式碼
2. 展開運算子:...要展開的東西
const arr1 = [3, 67, 8, 5];
//克隆arr1陣列到arr2
const arr2 = [0, ...arr1, 1];
console.log(arr2, arr1 === arr2)
// -------------------------------------
const obj1 = {
name: "A",
age: 18,
love: "B",
address: {
country: "中國",
province: "BJ",
city: "BJ"
}
}
// 淺克隆到obj2
const obj2 = {
...obj1,
name: "C"
};
console.log(obj2)
console.log(obj1.address === obj2.address)
複製程式碼
3. 明確函式的雙重用途
ES6提供了一個特殊的API,可以使用該API在函式內部,判斷該函式是否使用了new來呼叫
new.target
//該表示式,得到的是:如果沒有使用new來呼叫函式,則返回undefined
//如果使用new呼叫函式,則得到的是new關鍵字後面的函式本身
function Person(firstName, lastName) {
//判斷是否是使用new的方式來呼叫的函式
// //過去的判斷方式
// if (!(this instanceof Person)) {
// throw new Error("該函式沒有使用new來呼叫")
// }
if (new.target === undefined) {
throw new Error("該函式沒有使用new來呼叫")
}
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`;
}
const p1 = new Person("張", "三");
console.log(p1)
const p2 = Person("張", "三");
console.log(p2); // 報錯,該函式沒有使用new來呼叫
const p3 = Person.call(p1, "張", "三")
console.log(p3);// 報錯,該函式沒有使用new來呼叫
複製程式碼
4. 箭頭函式
-
ES5中this的問題(本文主要是來介紹ES6的,暫且將之前的總結直接放在這裡,在之後的博文中會仔細描述一下ES5系列)
- 通過物件呼叫函式,this指向物件
- 直接呼叫函式,this指向全域性物件
- 如果通過new呼叫函式,this指向新建立的物件
- 如果通過apply、call、bind呼叫函式,this指向指定的資料
- 如果是DOM事件函式,this指向事件源
-
箭頭函式是一個函式表示式,理論上,任何使用函式表示式的場景都可以使用箭頭函式
完整語法:
(引數1, 引數2, ...)=>{
//函式體
}
複製程式碼
如果引數只有一個,可以省略小括號
引數 => {
}
複製程式碼
如果箭頭函式只有一條返回語句,可以省略大括號,和return關鍵字
引數 => 返回值
複製程式碼
const print = num => {
console.log("給我的數字是:", num)
}
print(2);
const arr = [1,2,4,56,22,43,23,2,23,12,1];
arr.sort((a, b)=> a - b);
console.log(arr);
複製程式碼
注意
- 箭頭函式中,不存在this、arguments、new.target,如果使用了,則使用的是函式外層的對應的this、arguments、new.target 也就是說在箭頭函式中,this是固定的。因為箭頭函式本身就是引用的外層函式的this
- 箭頭函式沒有原型
- 箭頭函式不能作用建構函式使用
- 不可以使用yield命令,因此箭頭函式不能用作 Generator 函式
// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}
複製程式碼
除了this,arguments、super、new.target這三個變數在箭頭函式之中也是不存在的,指向外層函式的對應變數:arguments、super、new.target。
function foo() {
setTimeout(() => {
console.log('args:', arguments);
}, 100);
}
foo(2, 4, 6, 8)
// args: [2, 4, 6, 8]
複製程式碼
另外,由於箭頭函式沒有自己的this,所以當然也就不能用call()、apply()、bind()這些方法去改變this的指向。
(function() {
return [
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' });
// ['outer']
//程式碼中,箭頭函式沒有自己的this,所以bind方法無效,內部的this指向外部的this。
複製程式碼
應用比較多的場景
- 臨時性使用的函式,並不會可以呼叫它,比如:
- 事件處理函式
- 非同步處理函式
- 其他臨時性的函式
- 為了繫結外層this的函式
- 在不影響其他程式碼的情況下,保持程式碼的簡潔,最常見的,陣列方法中的回撥函式
本文主要引用阮一峰老師的《ECMAScript6簡介》
- es6.ruanyifeng.com/#README,大家可以多讀幾遍這本書,我所總結的只是目前工作中常用的,而書中有很多其他的我沒有提到的知識。
感謝大家能讀到最後,我再說兩點。
- 這是博主的第一篇文章,文章內容肯定會有很多的問題,希望大家可以多多提意見。小弟在此先送上感謝。
- ES6系列總結這邊暫時我打算分成4篇,這是第一篇,已經開始了,就要把這個東東搞完。所以希望有興趣的小夥伴們能加個關注,以便後續的文章第一時間通知到大家。