溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ES6中函數(shù)擴(kuò)展的示例

發(fā)布時(shí)間:2020-12-08 09:57:58 來(lái)源:億速云 閱讀:105 作者:小新 欄目:web開發(fā)

這篇文章給大家分享的是有關(guān)ES6中函數(shù)擴(kuò)展的示例的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧。

函數(shù)參數(shù)的默認(rèn)值

ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面。  

ES6之前:

function makeRequest(url,timeout,callback) {
    timeout=(typeof timeout!=="undefined")?timeout:2000;
    callback=(typeof callback!=="undefined")?callback:function(){};
                //    函數(shù)的剩余部分
}
//ES6 
function log(x, y = 'World') {
  console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

參數(shù)變量是默認(rèn)聲明的,所以不能用let或const再次聲明。

function foo(x = 5) {
  let x = 1; // error
  const x = 2; // error
}

使用參數(shù)默認(rèn)值時(shí),函數(shù)不能有同名參數(shù)。

// 不報(bào)錯(cuò)
function foo(x, x, y) {
  // ...
}
// 報(bào)錯(cuò)
function foo(x, x, y = 1) {
  // ...
}
// SyntaxError: Duplicate parameter name not allowed in this context

參數(shù)默認(rèn)值不是傳值的,而是每次都重新計(jì)算默認(rèn)值表達(dá)式的值。也就是說(shuō),參數(shù)默認(rèn)值是惰性求值的。

let x = 99;
function foo(p = x + 1) {
  console.log(p);
}
foo() // 100
x = 100;
foo() // 101

在函數(shù)聲明中能指定任意一個(gè)參數(shù)的默認(rèn)值,即使該參數(shù)排在未指定默認(rèn)值的參數(shù)之前也是可以的。

function makeRequest(ur1,timeout=2000,callback){
//函數(shù)的剩余部分
}
//    使用默認(rèn)的    timeout
makeRequest("/foo",    undefined,    function(body)    {
    doSomething(body);
});
//    使用默認(rèn)的    timeout
makeRequest("/foo");
//    不使用默認(rèn)值
makeRequest("/foo",    null,    function(body)    {
    doSomething(body);
});

在本例中,只有在未傳遞第二個(gè)參數(shù)、或明確將第二個(gè)參數(shù)值指定為undefined時(shí),timeout的默認(rèn)值才會(huì)被使用。

與解構(gòu)賦值默認(rèn)值結(jié)合使用

function foo({x, y = 5}) {
  console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined

上面代碼只使用了對(duì)象的解構(gòu)賦值默認(rèn)值,沒有使用函數(shù)參數(shù)的默認(rèn)值。只有當(dāng)函數(shù)foo的參數(shù)是一個(gè)對(duì)象時(shí),變量x和y才會(huì)通過(guò)解構(gòu)賦值生成。如果函數(shù)foo調(diào)用時(shí)沒提供參數(shù),變量x和y就不會(huì)生成,從而報(bào)錯(cuò)。通過(guò)提供函數(shù)參數(shù)的默認(rèn)值,就可以避免這種情況。

function foo({x, y = 5} = {}) {
  console.log(x, y);
}
foo() // undefined 5
function fetch(url, { body = '', method = 'GET', headers = {} }) {
  console.log(method);
}
fetch('http://example.com', {})
// "GET"
fetch('http://example.com')
// 報(bào)錯(cuò)
function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {
  console.log(method);
}
fetch('http://example.com')
// "GET"

會(huì)影響函數(shù)的length屬性

指定了默認(rèn)值以后,函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個(gè)數(shù)。也就是說(shuō),指定了默認(rèn)值后,length屬性將失真。

(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2

上面代碼中,length屬性的返回值,等于函數(shù)的參數(shù)個(gè)數(shù)減去指定了默認(rèn)值的參數(shù)個(gè)數(shù)。比如,上面最后一個(gè)函數(shù),定義了3個(gè)參數(shù),其中有一個(gè)參數(shù)c指定了默認(rèn)值,因此length屬性等于3減去1,最后得到2。  
這是因?yàn)閘ength屬性的含義是,該函數(shù)預(yù)期傳入的參數(shù)個(gè)數(shù)。某個(gè)參數(shù)指定默認(rèn)值以后,預(yù)期傳入的參數(shù)個(gè)數(shù)就不包括這個(gè)參數(shù)了。同理,后文的 rest 參數(shù)也不會(huì)計(jì)入length屬性。

(function(...args) {}).length // 0

如果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù),那么length屬性也不再計(jì)入后面的參數(shù)了

(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1

參數(shù)默認(rèn)值的作用域

一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域(context)。等到初始化結(jié)束,這個(gè)作用域就會(huì)消失。這種語(yǔ)法行為,在不設(shè)置參數(shù)默認(rèn)值時(shí),是不會(huì)出現(xiàn)的。

var x = 1;
function f(x, y = x) {
  console.log(y);
}
f(2) // 2
let x = 1;

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // 1

參數(shù)初始化會(huì)在函數(shù)被調(diào)用時(shí)進(jìn)行,無(wú)論是給參數(shù)傳遞了一個(gè)值、還是使用了參數(shù)的默認(rèn)值。  
上面代碼中,函數(shù)f調(diào)用時(shí),參數(shù)y = x形成一個(gè)單獨(dú)的作用域。這個(gè)作用域里面,變量x本身沒有定義,所以指向外層的全局變量x。函數(shù)調(diào)用時(shí),函數(shù)體內(nèi)部的局部變量x影響不到默認(rèn)值變量x。如果此時(shí),全局變量x不存在,就會(huì)報(bào)錯(cuò)。

var x = 1;
function foo(x, y = function() { x = 2; }) {
  var x = 3;
  y();
  console.log(x);
}
foo() // 3
x // 1

上面代碼中,函數(shù)foo的參數(shù)形成一個(gè)單獨(dú)作用域。這個(gè)作用域里面,首先聲明了變量x,然后聲明了變量y,y的默認(rèn)值是一個(gè)匿名函數(shù)。這個(gè)匿名函數(shù)內(nèi)部的變量x,指向同一個(gè)作用域的第一個(gè)參數(shù)x。函數(shù)foo內(nèi)部又聲明了一個(gè)內(nèi)部變量x,該變量與第一個(gè)參數(shù)x由于不是同一個(gè)作用域,所以不是同一個(gè)變量,因此執(zhí)行y后,內(nèi)部變量x和外部全局變量x的值都沒變。  
如果將var x =3的var去除,函數(shù)foo的內(nèi)部變量x就指向第一個(gè)參數(shù)x,與匿名函數(shù)內(nèi)部的x是一致的,所以最后輸出的就是2,而外層的全局變量x依然不受影響。

var x = 1;
function foo(x, y = function() { x = 2; }) {
  x = 3;
  y();
  console.log(x);
}
foo() // 2
x // 1

參數(shù)默認(rèn)值的暫時(shí)性死區(qū)

與1et聲明相似,函數(shù)每個(gè)參數(shù)都會(huì)創(chuàng)建一個(gè)新的標(biāo)識(shí)符綁定,它在初始化之前不允許被訪問(wèn),否則會(huì)拋出錯(cuò)誤。參數(shù)初始化會(huì)在函數(shù)被調(diào)用時(shí)進(jìn)行,無(wú)論是給參數(shù)傳遞了一個(gè)值、還是使用了參數(shù)的默認(rèn)值。

function    getValue(value)    {
    return    value    +    5;
}
function    add(first,    second    =    getValue(first))    {
    return    first    +    second;
}
console.log(add(1,    1));//    2
console.log(add(1));//    7

調(diào)用add(1,    1)和add(1)事實(shí)上執(zhí)行了以下代碼來(lái)創(chuàng)建first與second的參數(shù)值:

//JS調(diào)用add(1,1)可表示為
let    first    =    1;
let    second    =    1;
//JS調(diào)用add(1)可表示為
let    first    =    1;
let    second    =    getValue(first);

改寫一下

function    add(first    =    second,    second)    {
    return    first    +    second;
}

console.log(add(1,    1));//    2
console.log(add(undefined,    1));//    拋出錯(cuò)誤

本例中調(diào)用    add(1,    1)    與    add(undefined,    1)    對(duì)應(yīng)著以下的后臺(tái)代碼:

//    JS    調(diào)用    add(1,    1)    可表示為
let    first    =    1;
let    second    =    1;

//    JS    調(diào)用    add(1)    可表示為
let    first    =    second;
let    second    =    1;

本例中調(diào)用add(undefined,1)拋出了錯(cuò)誤,是因?yàn)樵趂irst被初始化時(shí)second尚未被初始化。此處的second存在于暫時(shí)性死區(qū)內(nèi),對(duì)于second的引用就拋出了錯(cuò)誤。  
函數(shù)參數(shù)擁有各自的作用域和暫時(shí)性死區(qū),與函數(shù)體的作用域相分離,這意味著參數(shù)的默認(rèn)值不允許訪問(wèn)在函數(shù)體內(nèi)部聲明的任意變量。

應(yīng)用

利用參數(shù)默認(rèn)值,可以指定某一個(gè)參數(shù)不得省略,如果省略就拋出一個(gè)錯(cuò)誤。

function throwIfMissing() {
  throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
  return mustBeProvided;
}
foo()
// Error: Missing parameter

rest 參數(shù)

ES6 引入 rest參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了。rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。rest參數(shù)就是一個(gè)真正的數(shù)組,數(shù)組特有的方法都可以使用。

function add(...values) {
  let sum = 0;
  for (var val of values) {
    sum += val;
  }
  return sum;
}
add(2, 5, 3) // 10
// arguments變量的寫法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}
// rest參數(shù)的寫法
const sortNumbers = (...numbers) => numbers.sort();

rest 參數(shù)的限制條件

一是函數(shù)只能有一個(gè)剩余參數(shù),并且它必須被放在最后。

// 報(bào)錯(cuò)
function f(a, ...b, c) {
  // ...
}

第二個(gè)限制是剩余參數(shù)不能在對(duì)象字面量的    setter    屬性中使用,這意味著如下代碼同樣會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤:

1et object={
//語(yǔ)法錯(cuò)誤:不能在setter中使用剩余參數(shù)
set name(...value){
//一些操作
};

存在此限制的原因是:對(duì)象字面量的setter被限定只能使用單個(gè)參數(shù);而剩余參數(shù)按照定義是不限制參數(shù)數(shù)量的,因此它在此處不被許可。    
前面有講函數(shù)的length屬性,不包括 rest 參數(shù)。

(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1

嚴(yán)格模式

從 ES5 開始,函數(shù)內(nèi)部可以設(shè)定為嚴(yán)格模式。

function doSomething(a, b) {
  'use strict';
  // code
}

ES2016 做了一點(diǎn)修改,規(guī)定只要函數(shù)參數(shù)使用了默認(rèn)值、解構(gòu)賦值、或者擴(kuò)展運(yùn)算符,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式,否則會(huì)報(bào)錯(cuò)。

// 報(bào)錯(cuò)
function doSomething(a, b = a) {
  'use strict';
  // code
}
// 報(bào)錯(cuò)
const doSomething = function ({a, b}) {
  'use strict';
  // code
};
// 報(bào)錯(cuò)
const doSomething = (...a) => {
  'use strict';
  // code
};
const obj = {
  // 報(bào)錯(cuò)
  doSomething({a, b}) {
    'use strict';
    // code
  }
};

這樣規(guī)定的原因是,函數(shù)內(nèi)部的嚴(yán)格模式,同時(shí)適用于函數(shù)體和函數(shù)參數(shù)。但是,函數(shù)執(zhí)行的時(shí)候,先執(zhí)行函數(shù)參數(shù),然后再執(zhí)行函數(shù)體。這樣就有一個(gè)不合理的地方,只有從函數(shù)體之中,才能知道參數(shù)是否應(yīng)該以嚴(yán)格模式執(zhí)行,但是參數(shù)卻應(yīng)該先于函數(shù)體執(zhí)行。  
把函數(shù)包在一個(gè)無(wú)參數(shù)的立即執(zhí)行函數(shù)里面可以規(guī)避這種限制。

const doSomething = (function () {
  'use strict';
  return function(value = 42) {
    return value;
  };
}());

在代碼塊中聲明函數(shù)

在ES3或更早版本中,在代碼塊中聲明函數(shù)(即塊級(jí)函數(shù))嚴(yán)格來(lái)說(shuō)應(yīng)當(dāng)是一個(gè)語(yǔ)法錯(cuò)誤,但所有的瀏覽器卻都支持該語(yǔ)法??上У氖?,每個(gè)支持該語(yǔ)法的瀏覽器都有輕微的行為差異,所以最佳實(shí)踐就是不要在代碼塊中聲明函數(shù)(更好的選擇是使用函數(shù)表達(dá)式)。

嚴(yán)格模式下

為了控制這種不兼容行為,ES5的嚴(yán)格模式為代碼塊內(nèi)部的函數(shù)聲明引入了一個(gè)錯(cuò)誤。  
然而ES6會(huì)將    doSomething()函數(shù)視為塊級(jí)聲明,并允許它在定義所在的代碼塊內(nèi)部被訪問(wèn)。塊級(jí)函數(shù)與    let    函數(shù)表達(dá)式相似,在執(zhí)行流跳出定義所在的代碼塊之后,函數(shù)定義就會(huì)被移除。關(guān)鍵區(qū)別在于:塊級(jí)函數(shù)會(huì)被提升到所在代碼塊的頂部;而使用let的函數(shù)表達(dá)式則不會(huì) 。

"use    strict";
if    (true)    {

    console.log(typeof doSomething);//"function"
    function    doSomething()    {
        //    ...
    }
    doSomething();
}
console.log(typeof    doSomething);//    "undefined

非嚴(yán)格模式下

ES6    在非嚴(yán)格模式下同樣允許使用塊級(jí)函數(shù),但行為有細(xì)微不同。塊級(jí)函數(shù)的作用域會(huì)被提升到所在函數(shù)或全局環(huán)境的頂部,而不是代碼塊的頂部。

//    ES6    behavior
if    (true)    {
    console.log(typeof    doSomething);//"function"
    function    doSomething()    {
        //    ...
    }
    doSomething();
}
console.log(typeof    doSomething);//    "function"

name 屬性

函數(shù)的name屬性,返回該函數(shù)的函數(shù)名。

function foo() {}
foo.name // "foo"

getter函數(shù),因此它的名稱是    "get    firstName"    ,以標(biāo)明它的特征;同樣,setter函數(shù)也會(huì)帶有"set"的前綴(getter與setter函數(shù)都必須用Object.getOwnPropertyDescriptor()來(lái)檢索)。另外,使用bind()創(chuàng)建的函數(shù)會(huì)在名稱屬性值之前帶有"bound”前綴;而使用Function構(gòu)造器創(chuàng)建的函數(shù),其名稱屬性則會(huì)有“anonymous”前綴,如果將一個(gè)匿名函數(shù)賦值給一個(gè)變量,ES5的name屬性,會(huì)返回空字符串,而 ES6 的name屬性會(huì)返回實(shí)際的函數(shù)名。

var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"

new.target元屬性

JS為函數(shù)提供了兩個(gè)不同的內(nèi)部方法:[[Call]]與[[Construct]]。當(dāng)函數(shù)未使用new進(jìn)行調(diào)用時(shí),[[Call]]方法會(huì)被執(zhí)行,運(yùn)行的是代碼中顯示的函數(shù)體。而當(dāng)函數(shù)使用new進(jìn)行調(diào)用時(shí),[[Construct]]方法則會(huì)被執(zhí)行,負(fù)責(zé)創(chuàng)建一個(gè)被稱為新目標(biāo)的新的對(duì)象,并且使用該新目標(biāo)作為this去執(zhí)行函數(shù)體。擁有[[Construct]]    方法的函數(shù)被稱為構(gòu)造器。記住并不是所有函數(shù)都擁有[[Construct]]方法,因此不是所有函數(shù)都可以用new來(lái)調(diào)用。

在ES5中判斷函數(shù)如何被調(diào)用

在ES5中判斷函數(shù)是不是使用了new來(lái)調(diào)用(即作為構(gòu)造器),最流行的方式是使用instanceof,例如:

function    Person(name)    {
    if    (this    instanceof    Person)    {
            this.name    =    name;//    使用new
    }    else    {
            throw    new    Error("You    must    use    new    with    Person
    }
}

var    person    =    new    Person("Nicholas");
var    notAPerson    =    Person("Nicholas");//拋出錯(cuò)誤

可惜的是,該方法并不絕對(duì)可靠,因?yàn)樵诓皇褂?   new    的情況下this仍然可能是    Person    的實(shí)例。

var    notAPerson    =    Person.call(person,    "Michael");    //    奏效了!

在ES6中判斷函數(shù)如何被調(diào)用

為了解決這個(gè)問(wèn)題,ES6引入了new.target 元屬性。元屬性指的是“非對(duì)象”(例如new)上的一個(gè)屬性,并提供關(guān)聯(lián)到它的目標(biāo)的附加信息。當(dāng)函數(shù)的[[Construct]]方法被調(diào)用時(shí),new.target 會(huì)被填入new運(yùn)算符的作用目標(biāo),該目標(biāo)通常是新創(chuàng)建的對(duì)象實(shí)例的構(gòu)造器,并且會(huì)成為函數(shù)體內(nèi)部的this值。而若[[Call]]被執(zhí)行,new.target的值則會(huì)是undefined。    
通過(guò)檢查new.target是否被定義,這個(gè)新的元屬性就讓你能安全地判斷函數(shù)是否被使用new 進(jìn)行了調(diào)用。

function    Person(name)    {
    if    (typeof new.target    !==    "undefined")    {
            this.name    =    name;//    使用new
    }    else    {
            throw    new    Error("You    must    use    new    with    Person
    }
}
var    person    =    new    Person("Nicholas");
var    notAPerson    =    Person("Nicholas");//拋出錯(cuò)誤

警告:在函數(shù)之外使用new.target會(huì)有語(yǔ)法錯(cuò)誤。

箭頭函數(shù)

ES6 允許使用“箭頭”(=>)定義函數(shù)。但它的行為在很多重要方面與傳統(tǒng)的JS函數(shù)不同:

區(qū)別

  • 沒有this、super、arguments,也沒有new.target 綁定:this、super、arguments、以及函數(shù)內(nèi)部的new.target的值由所在的、最靠近的非箭頭函數(shù)來(lái)決定。

  • 不能被使用new調(diào)用:箭頭函數(shù)沒有[[Construct]]方法,因此不能被用為構(gòu)造函數(shù),使用new調(diào)用箭頭函數(shù)會(huì)拋出錯(cuò)誤。

  • 沒有原型:既然不能對(duì)箭頭函數(shù)使用new,那么它也不需要原型,也就是沒有prototype 屬性。

  • 不能更改this:this的值在函數(shù)內(nèi)部不能被修改,在函數(shù)的整個(gè)生命周期內(nèi)其值會(huì)保持不變。

  • 沒有arguments對(duì)象:既然箭頭函數(shù)沒有arguments綁定,你必須依賴于具名參數(shù)或剩余參數(shù)來(lái)訪問(wèn)函數(shù)的參數(shù)。

  • 不允許重復(fù)的具名參數(shù):箭頭函數(shù)不允許擁有重復(fù)的具名參數(shù),無(wú)論是否在嚴(yán)格模式下;而相對(duì)來(lái)說(shuō),傳統(tǒng)函數(shù)只有在嚴(yán)格模式下才禁止這種重復(fù)。

  • 不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句,就要使用大括號(hào)將它們括起來(lái),并且使用return語(yǔ)句返回。

var sum = (num1, num2) => { return num1 + num2; }

由于大括號(hào)被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個(gè)對(duì)象,必須在對(duì)象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)。

// 報(bào)錯(cuò)
let getTempItem = id => { id: id, name: "Temp" };

// 不報(bào)錯(cuò)
let getTempItem = id => ({ id: id, name: "Temp" });

下面是一種特殊情況,雖然可以運(yùn)行,但會(huì)得到錯(cuò)誤的結(jié)果。

let foo = () => { a: 1 };
foo() // undefined

上面代碼中,原始意圖是返回一個(gè)對(duì)象{a:1},但是由于引擎認(rèn)為大括號(hào)是代碼塊,所以執(zhí)行了一行語(yǔ)句a: 1。這時(shí),a可以被解釋為語(yǔ)句的標(biāo)簽,因此實(shí)際執(zhí)行的語(yǔ)句是1;,然后函數(shù)就結(jié)束了,沒有返回值。  
如果箭頭函數(shù)只有一行語(yǔ)句,且不需要返回值,可以采用下面的寫法,就不用寫大括號(hào)了。

let fn = () => void doesNotReturn();

this指向的固定化,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因?yàn)樗鼪]有this,所以也就不能用作構(gòu)造函數(shù)。  
所以,箭頭函數(shù)轉(zhuǎn)成 ES5 的代碼如下。

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

箭頭函數(shù)的this看外層的是否有函數(shù)

如果有,外層函數(shù)的this就是內(nèi)部箭頭函數(shù)的this。

 function Person() {
     this.obj = {
         showThis : () => {
             console.log(this);//person
         }
     }
 }
    let fun5 = new Person();
    fun5.obj.showThis();

如果沒有,this值就會(huì)是全局對(duì)象(在瀏覽器中是window,在nodejs中是global)。

    let obj = {
        name : 'kobe',
        age : 39,
        getName : () => {
            btn2.onclick = () => {
                console.log(this);//window
            };
        }
    };
    obj.getName();

不適用的場(chǎng)合

由于箭頭函數(shù)使得this從“動(dòng)態(tài)”變成“靜態(tài)”,下面兩個(gè)場(chǎng)合不應(yīng)該使用箭頭函數(shù)。  
第一個(gè)場(chǎng)合是定義函數(shù)的方法,且該方法內(nèi)部包括this。

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

第二個(gè)場(chǎng)合是需要?jiǎng)討B(tài)this的時(shí)候,也不應(yīng)使用箭頭函數(shù)。

var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});

上面代碼運(yùn)行時(shí),點(diǎn)擊按鈕會(huì)報(bào)錯(cuò),因?yàn)閎utton的監(jiān)聽函數(shù)是一個(gè)箭頭函數(shù),導(dǎo)致里面的this就是全局對(duì)象。如果改成普通函數(shù),this就會(huì)動(dòng)態(tài)指向被點(diǎn)擊的按鈕對(duì)象。  
另外,如果函數(shù)體很復(fù)雜,有許多行,或者函數(shù)內(nèi)部有大量的讀寫操作,不單純是為了計(jì)算值,這時(shí)也不應(yīng)該使用箭頭函數(shù),而是要使用普通函數(shù),這樣可以提高代碼可讀性。

雙冒號(hào)運(yùn)算符

箭頭函數(shù)可以綁定this對(duì)象,大大減少了顯式綁定this對(duì)象的寫法(call、apply、bind)。但是,箭頭函數(shù)并不適用于所有場(chǎng)合,所以現(xiàn)在有一個(gè)提案,提出了“函數(shù)綁定”(function bind)運(yùn)算符,用來(lái)取代call、apply、bind調(diào)用。  
函數(shù)綁定運(yùn)算符是并排的兩個(gè)冒號(hào)(::),雙冒號(hào)左邊是一個(gè)對(duì)象,右邊是一個(gè)函數(shù)。該運(yùn)算符會(huì)自動(dòng)將左邊的對(duì)象,作為上下文環(huán)境(即this對(duì)象),綁定到右邊的函數(shù)上面。

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}

如果雙冒號(hào)左邊為空,右邊是一個(gè)對(duì)象的方法,則等于將該方法綁定在該對(duì)象上面。

var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

感謝各位的閱讀!關(guān)于ES6中函數(shù)擴(kuò)展的示例就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI