第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

ES6+ 箭頭函數(shù)

1. 前言

在編程中使用最多的就是函數(shù),在 ES5 中是用 function 關(guān)鍵字來定義函數(shù)的,由于歷史原因 function 定義的函數(shù)存在一些問題,如 this 的指向、函數(shù)參數(shù) arguments 等。

ES6 規(guī)定了可以使用 “箭頭” => 來定義一個函數(shù),語法更加簡潔。它沒有自己的 thisargumentssupernew.target,箭頭函數(shù)表達(dá)式更適用于那些本來需要匿名函數(shù)的地方,但它不能用作構(gòu)造函數(shù)。

2. this 指向

在 JavaScript 中,要說讓人最頭疼的知識點中,this 綁定絕對算一個,這是因為 this 的綁定 ‘難以捉摸’,出錯的時候還往往不知道為什么,相當(dāng)反邏輯。下面我們來看一個示例:

var title = "全局標(biāo)題";
var imooc = {
	title: "慕課網(wǎng) ES6 Wiki",
	getTitle : function(){
		console.log(this.title);
	}
};
imooc.getTitle();		// 慕課網(wǎng) ES6 Wiki
var bar = imooc.getTitle;
bar();		// 全局標(biāo)題

通過上面的小例子的打印結(jié)果可以看出 this 的問題,說明 this 的指向是不固定的。

這里簡單說明一下 this 的指向,this 指向的是調(diào)用它的對象。例子中的 this 是在 getTitle 的函數(shù)中的,執(zhí)行 imooc.getTitle() 這個方法時,調(diào)用它的對象是 imooc,所以 this 的指向是 imooc。

之后把 imooc.getTitle 方法賦給 bar,這里要注意的是,只是把地址賦值給了 bar ,并沒有調(diào)用。 而 bar 是全局對象 window 下的方法,所以在執(zhí)行 bar 方法時,調(diào)用它的是 Window 對象,所以這里打印的結(jié)果是 window 下的 title——“全局標(biāo)題”。

TIPS: 上面的示例只是簡單的 this 指向問題,還有很多更加復(fù)雜的,在面試中經(jīng)常會被問到,所以還不清楚的同學(xué)可以去研究一下 this 的問題。

ES6 為了規(guī)避這樣的問題,提出了箭頭函數(shù)的解決方案,在箭頭函數(shù)中沒有自己的 this 指向,所有的 this 指向都指向它的上一層 this ,這樣規(guī)定就比較容易理解了。下面看使用箭頭函數(shù)下的 this 指向:

var title = "全局標(biāo)題";
var imooc = {
	title: "慕課網(wǎng) ES6 Wiki",
	getTitle : () => {
		console.log(this.title);
	}
};
imooc.getTitle();		// 全局標(biāo)題
var bar = imooc.getTitle;
bar();		// 全局標(biāo)題

上面的打印結(jié)果可以看出來,所有的 this 指向都指向了 window 對象下的 title,本身的 imooc 對象下沒有了 this ,它的上一層就是 window。

3. 語法詳解

3.1 基本語法

箭頭函數(shù)的使用很簡單,使用 => 來定義函數(shù),下面對比 ES5 和 ES6 定義函數(shù)的對比。

// ES5
var sum = function () {
  // todo
};
// ES6
var sum = () => {
  // todo
}

3.2 有返回值

當(dāng)函數(shù)體內(nèi)有返回值時,ES6 的箭頭函數(shù)可以省略大括號:

var sum = (num1, num2) => num1 + num2;

當(dāng)傳遞的參數(shù)只有一個時,圓括號也可以省略:

var sum = num => num + 10;

下面看個使用 map 求和的例子:

// ES5
[1,2,3].map(function (x) {
  return x * x;
});
// 等同于ES6
[1,2,3].map(x => x * x);

對比 ES5 可以看出箭頭函數(shù)的簡潔表達(dá),更加準(zhǔn)確明了。

3.3 返回值是對象

如果函數(shù)體返回對象字面量表達(dá)式,可以省略大括號,使用圓括號的形式包裹對象。

var getimooc = () => ({a: 1, b: 2});
getimooc()  // {a: 1, b: 2}

3.4 默認(rèn)參數(shù)

在定義函數(shù)時,往往需要給參數(shù)添加默認(rèn)值,ES6 中可以直接在圓括號中進行賦值。

var sum = (num1, num2 = 2) => num1 + num2;
console.log(sum(1))   // 3

在使用 function 關(guān)鍵字定義函數(shù)時,如果要給傳遞的參數(shù)設(shè)置默認(rèn)參數(shù),只能在函數(shù)體內(nèi)進行賦值操作,ES6 簡化了默認(rèn)參數(shù)的賦值過程。

3.5 剩余參數(shù)

函數(shù)在接收不定參數(shù)時,可以使用剩余運算符把調(diào)用函數(shù)時傳入的參數(shù)聚攏起來成為一個參數(shù)數(shù)組(類似 function 中的 arguments 對象,但 arguments 不是數(shù)組,不能直接使用)。

下面是剩余參數(shù)的例子:

var fun = (param1, param2, ...rest) => {
  console.log(param1)
  console.log(param2)
  console.log(rest)
};
fun(1, 2, 3, 4, 5);
// 1
// 2
// [3, 4, 5]

4. 沒有 this

箭頭函數(shù)不會創(chuàng)建自己的 this,它只會從自己的作用域鏈的上一層繼承 this,setTimeout 會改變 this 的指向,看下面的示例:

// 在構(gòu)造函數(shù)中
function Person(){
  this.age = 0;
  setTimeout(function(){
    console.log(this);
  }, 1000)
}
var p = new Person();   // Window: {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

function Person(){
  this.age = 0;
  setTimeout(() => {
    console.log(this);
  }, 1000);
}
var p = new Person();   // Person: {age: 0}

第一個例子中的 setTimeout 的回調(diào)函數(shù)使用 function 來定義的,從打印的結(jié)果可以看出 this 的指向是 window 對象也就是全局作用域。而第二個示例中 setTimeout 的回調(diào)函數(shù)使用箭頭函數(shù)來定義,打印的結(jié)果可以看到,this 的指向是 Person.

一個實例: 定義為一個構(gòu)造函數(shù) Person,在函數(shù)中定義一個 imooc 對象,使用 function 關(guān)鍵字和箭頭函數(shù)的方式給 imooc 上添加 getValue 方法,最后返回 imooc 對象,這時候我們來觀察 getValue 內(nèi)的 this 指向問題。

function Person(){
  var imooc = {};
  imooc.num = 10;
  imooc.getValue = () => {
    console.log(this)
  }
  return imooc;
}
var p = new Person();
p.getValue()
// person {} 

上面的示例中,構(gòu)造函數(shù)中 imooc.getValue 方法使用的是箭頭函數(shù)定義的,所以 getValue 方法不會有 this 的指向,它會根據(jù)作用域鏈向上查找到 Person 構(gòu)造函數(shù),所以這里的 this 的指向是 Person

function Person(){
  var imooc = {};
  imooc.num = 10;
  imooc.getValue = function() {
    console.log(this)
  }
  return imooc;
}
var p = new Person();
p.getValue()
// {num: 10, getValue: ?}   this指向的是 p 的返回值

上面的示例中,構(gòu)造函數(shù)中 imooc.getValue 方法是使用 function 定義的,所以 getValue 中 this 的指向是動態(tài)的,指向調(diào)用它的那個對象。在 new Person() 時,會返回 imooc 對象賦給實例 ,在使用 p 去調(diào)用 getValue()this 的指向就是 p 實例。

總結(jié): 箭頭函數(shù)的 this 永遠(yuǎn)指向的是父級作用域。

5. 不綁定 arguments

箭頭函數(shù)不綁定 Arguments 對象。所以在使用箭頭函數(shù)定義的函數(shù)體內(nèi)是取不到 arguments 的。

var fun = function() {
  console.log(arguments)
};
fun(1,2,3);  // Arguments(3) [1, 2, 3, callee: ?, Symbol(Symbol.iterator): ?]

var fun = () => {
  console.log(arguments)
};
fun(1,2,3);  // Uncaught ReferenceError: arguments is not defined

上面的示例中,對比兩種定義函數(shù)的方法可以明顯的看出,在箭頭函數(shù)中去取 arguments 時會報引用錯誤,沒有定義的 arguments。

arguments 的主要作用是獲取所有調(diào)用函數(shù)時所需要傳入的參數(shù),在箭頭函數(shù)中使用剩余參數(shù) ...args,在函數(shù)內(nèi)可以直接使用。

function foo(...args) { 
  console.log(args)
}
foo(1);         // [1]
foo(1, 2, 3);   // [1, 2, 3]

6. 其他注意點

6.1 不能用作構(gòu)造器

箭頭函數(shù)不能用作構(gòu)造器,和 new 一起用會拋出錯誤。

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

6.2 沒有 prototype 屬性

箭頭函數(shù)沒有 prototype 屬性。

var Foo = () => {};
console.log(Foo.prototype); // undefined

6.3 不能使用 yield 命令

yield 關(guān)鍵字通常不能在箭頭函數(shù)中使用,因此箭頭函數(shù)不能用作 Generator 函數(shù)。

7. 小結(jié)

本節(jié)主要講解了 ES6 的箭頭函數(shù),總結(jié)了以下幾點:

  • 更短的函數(shù),優(yōu)雅簡潔;
  • 箭頭函數(shù)不會創(chuàng)建自己的 this,它只會從自己的作用域鏈的上一層繼承 this;
  • 不能綁定 arguments, 只能使用 ...args 展開運算來獲取當(dāng)前參數(shù)的數(shù)組。