摘要:但是三作為構造函數時函數其實還有一個非常重要的特點返回的函數如果作為構造函數,搭配關鍵字出現的話,我們的綁定就需要被忽略。其次,當返回的函數作為構造函數時,之前綁定的會失效。
本文共 1100 字,讀完只需 4 分鐘概述
前一篇文章我們嘗試模擬實現了 call 和 apply 方法,其實 bind 函數也可以用來改變 this 的指向。bind 和 call和 apply 兩者的區別在于,bind 會返回一個被改變了 this 指向的函數。
本文介紹如何模擬實現 bind 函數:
首先觀察 bind 函數有什么特點:
var person = { name: "jayChou" } function say(age, sex) { console.log(this.name, age, sex); } var foo = say.bind(person, "男", 39); foo(); // jayChou 男 39
返回一個函數
函數參數以逗號的形式傳入
改變了 this 的指向
一、call 簡單實現既然 bind 內部也要用改變 this 指向,我們可以用現成的 call 函數來實現這一功能。
Function.prototype.newBind = function(context) { if(typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; return function () { return self.call(context) } }
說明一下:
if 判斷是為了校驗,只能讓函數來調用此方法,并拋出錯誤。
第二個 return 是為了讓返回的函數有返回值的功能。
測試一下:
var person = { name: "jayChou" }; var say = function() { console.log(this.name); } var foo = say.newBind(person); foo(); // jayChou
成功啦。
二、傳遞參數剛才的函數是沒有傳遞參數,當然不行,所以我們想辦法把函數的參數也傳遞進去。
bind 函數有個特點,就是在綁定的時候可以傳參,返回的函數還可以繼續傳參。
var person = { name: "jayChou" }; var say = function(p1, p2) { console.log(this.name, p1, p2); } var foo = say.bind(person, 18); foo(20); // jayChou 18 20
還可以寫成:
say.bind(person, 18)(20); // jayChou 18 20
好,進入正題,考慮傳參的事。在前面的文章,我們講過 arguments 類數組對象的一些特性,不能直接調用數組的方法,但是可以用原型方法間接來調用,我們采用 apply 的方式來傳遞參數。
Function.prototype.newBind = function(context) { if(typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; var args = Array.prototype.slice.call(arguments, 1); // 間接調用數組方法,獲取第一次傳的參數 return function () { var innerArgs = Array.prototype.slice.call(arguments); return self.apply(context, args.concat(innerArgs)) } } var person = { name: "jayChou" }; var say = function(p1, p2) { console.log(this.name, p1, p2); } var foo = say.newBind(person, 18); // 第一次傳參 foo(20); // 第二次傳參
最后輸出:
jayChou 18 20
結果正確,以上就完成了 bind 函數基本功能的實現。
但是!
三、作為構造函數時?bind 函數其實還有一個非常重要的特點:
bind返回的函數如果作為構造函數,搭配new關鍵字出現的話,我們的綁定this就需要“被忽略”。
意思就是指:當使用 nuw 關鍵字把 bind 返回的函數作為構造函數,之前改變了指向的 this 就失效了。返回的函數的 this 就關聯到了構造函數的實例對象上。
針對這個特點,需要再做一些修改:
Function.prototype.newBind = function(context) { if(typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var self = this; var args = Array.prototype.slice.call(arguments, 1); // 間接調用數組方法,獲取第一次傳的參數 let tempFn = function {}; // 利用一個空函數作為中轉 tempFn.prototype = this.prototype; // 修改返回函數的 prototype 為綁定函數的 prototype,實例就可以繼承綁定函數的原型中的值 var resultFn = function () { var innerArgs = Array.prototype.slice.call(arguments); if (this instanceof tempFn) { // 如果 返回函數被當做構造函數后,生成的對象是 tempFn 的實例,此時應該將 this 的指向指向創建的實例。 return self.apply(this, args.concat(innerArgs)); } else { return self.apply(context, args.concat(innerArgs)) } } resultFn = new tempFn(); return resultFn; }總結
本文嘗試模擬實現了 bind 函數,bind 函數與 call,apply 函數的區別在于,bind 函數返回一個指定了 this 的函數,函數并未執行。其次,當返回的函數作為構造函數時,之前綁定的 this 會失效。
歡迎關注我的個人公眾號“謝南波”,專注分享原創文章。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98854.html
摘要:寫在前面深入系列共計篇已經正式完結,這是一個旨在幫助大家,其實也是幫助自己捋順底層知識的系列。深入系列自月日發布第一篇文章,到月日發布最后一篇,感謝各位朋友的收藏點贊,鼓勵指正。 寫在前面 JavaScript 深入系列共計 15 篇已經正式完結,這是一個旨在幫助大家,其實也是幫助自己捋順 JavaScript 底層知識的系列。重點講解了如原型、作用域、執行上下文、變量對象、this、...
摘要:專題系列第十四篇,講解偏函數以及如何實現一個函數定義維基百科中對偏函數的定義為翻譯成中文在計算機科學中,局部應用是指固定一個函數的一些參數,然后產生另一個更小元的函數。 JavaScript 專題系列第十四篇,講解偏函數以及如何實現一個 partial 函數 定義 維基百科中對偏函數 (Partial application) 的定義為: In computer science, pa...
摘要:引言上一節介紹了高階函數的定義,并結合實例說明了使用高階函數和不使用高階函數的情況。我們期望函數輸出,但是實際上調用柯里化函數時,所以調用時就已經執行并輸出了,而不是理想中的返回閉包函數,所以后續調用將會報錯。引言 上一節介紹了高階函數的定義,并結合實例說明了使用高階函數和不使用高階函數的情況。后面幾部分將結合實際應用場景介紹高階函數的應用,本節先來聊聊函數柯里化,通過介紹其定義、比較常見的...
摘要:模擬實現操作符構造函數返回結果創建一個空對象取傳入的第一個參數,即構造函數,并刪除第一個參數。二處理返回值構造函數也是函數,有不同類型返回值。有時候構造函數會返回指定的對象內容,所以要對這部分進行處理。 本文共 1230 字,讀完只需 5 分鐘 寫在前面 最近工作太忙,快接近兩周沒更新博客,總感覺有一些事情等著自己去做,雖然工作內容對自己提升挺大,但我總覺得,一直埋著頭走路,偶爾也...
閱讀 2335·2021-11-24 09:39
閱讀 3778·2021-11-19 09:40
閱讀 2153·2021-09-27 13:36
閱讀 1897·2019-08-30 15:44
閱讀 390·2019-08-30 13:52
閱讀 2713·2019-08-30 11:13
閱讀 2171·2019-08-29 16:18
閱讀 1756·2019-08-29 15:43