摘要:前言最近接觸到方法,為了加深理解,自己模擬實(shí)現(xiàn)一下。我們模擬的方法參考上的。基本上關(guān)于模擬的實(shí)現(xiàn)就是這樣。所以不能肯定剛才的就是總結(jié)完全重寫構(gòu)造函數(shù)原型對(duì)象要放在構(gòu)造函數(shù)后面,如果放在構(gòu)造函數(shù)里面,可能原型鏈會(huì)有錯(cuò)誤。
前言
最近接觸到bind方法,為了加深理解,自己模擬實(shí)現(xiàn)一下。
首先,談一下bind()方法的特點(diǎn):
把調(diào)用bind()的函數(shù)(以后統(tǒng)稱為初試函數(shù))中的this指向綁定到某個(gè)對(duì)象上,bind的第二個(gè)及其以后的參數(shù)作為作為 初始函數(shù)的 參數(shù),bind()執(zhí)行完返回一個(gè)新的函數(shù)。
新返回的函數(shù)如果用 new 字符來調(diào)用的話,那么之前this指向綁定到某個(gè)對(duì)象上 將會(huì)失效,并且初始函數(shù)中的this指向綁定到 new調(diào)用的 函數(shù)實(shí)例上。函數(shù)實(shí)例上還可以調(diào)用初始函數(shù)的原型上的方法
那么先實(shí)現(xiàn)第一個(gè)特點(diǎn)
// 因?yàn)樾枰泻瘮?shù)都能執(zhí)行,所以綁定到Function.prototype上 Function.prototype.bindFn=function(thisArg) { if(typeof this !== "function") { throw new TypeError(this+" is not a function"); } // 調(diào)用bindFn方法的函數(shù)的引用 var self = this; // 以數(shù)組形式保存第二個(gè)及其以后的參數(shù) var beforeArg = [].slice.call(arguments,1); var bound = function() { // 以數(shù)組形式保存著當(dāng)前函數(shù)的所有參數(shù) var afterArg = [].slice.call(arguments); // bindFn第二個(gè)及其以后的參數(shù)和當(dāng)前函數(shù)所有參數(shù)的 集合 // 全部傳到self函數(shù)的參數(shù)里 var finalArgs = beforeArg.concat(afterArg); // self中的this指向綁定到 thisArg return self.apply(thisArg, finalArgs); } return bound; } var obj1={sex:23}; function m1(a,b) { console.log(a+b); // 6 console.log(this); // {sex:23} } var bound=m1.bindFn(obj1,2); var result=bound(4);
可見m1中的this指向了obj1對(duì)象,2,4分別傳給了形參a,b。
進(jìn)一步完善bindFn,實(shí)現(xiàn)第二個(gè)特點(diǎn)
// 因?yàn)樾枰泻瘮?shù)都能執(zhí)行,所以綁定到Function.prototype上 Function.prototype.bindFn=function(thisArg) { if(typeof this !== "function") { throw new TypeError(this +" is not a function"); } // 調(diào)用bindFn方法的函數(shù)的引用 var self = this; // 以數(shù)組形式保存第二個(gè)及其以后的參數(shù) var beforeArg = [].slice.call(arguments,1); var bound = function() { // 以數(shù)組形式保存著當(dāng)前函數(shù)的所有參數(shù) var afterArg = [].slice.call(arguments); // bindFn第二個(gè)及其以后的參數(shù)和當(dāng)前函數(shù)所有參數(shù)的 集合 // 全部傳到self函數(shù)的參數(shù)里 var finalArgs = beforeArg.concat(afterArg); // 如果new調(diào)用的話,this指向?qū)嵗龑?duì)象 // 否則this指向需要綁定的對(duì)象 // this instanceof bound并不準(zhǔn)確,可以用es6中的new.target來解決 return self.apply(this instanceof bound ? this : thisArg, finalArgs); } // new調(diào)用的時(shí)候有用 // 避免es6中的箭頭函數(shù) // 箭頭函數(shù)沒有prototype if(this.prototype) { // 避免修改 bound.prototype 污染到 this.prototype function a(){} a.prototype=this.prototype; bound.prototype=new a(); bound.prototype.constructor=bound; } return bound; } var obj1={sex:23}; function m1(a,b) { this.name="m1"; console.log(a+b); // 6 console.log(this); // {name:"m1"} } m1.prototype.allKey=function() { console.log("this is allkey"); } var bound=m1.bindFn(obj1,2); var result=new bound(4); result.allKey(); // this is allkey
可見,m1中的this指向了result這個(gè)實(shí)例對(duì)象,并且result 通過原型鏈 繼承了m1.prototype上的方法。
那么我們看下官方bind的使用:
// 關(guān)鍵部分 function m1(a,b) { this.name="m1"; console.log(a+b); // 6 console.log(this); // {name:"m1"} } var bound=m1.bind(obj1,2); var result=new bound(4); result.allKey(); // this is allkey
由上圖可見,雖然原型鏈上有所不同,但我們模擬的方法還是實(shí)現(xiàn)了bind的功能。我們模擬的方法bindFn參考mdn上的Polyfill。基本上關(guān)于模擬bind的實(shí)現(xiàn)就是這樣。
現(xiàn)在我們?cè)谘由煲幌玛P(guān)于原型鏈的知識(shí),如果剛才的bound.prototype完全重寫在了bound構(gòu)造函數(shù)內(nèi),又會(huì)怎樣?
// 因?yàn)樾枰泻瘮?shù)都能執(zhí)行,所以綁定到Function.prototype上 Function.prototype.bindFn=function(thisArg) { if(typeof this !== "function") { throw new TypeError(this +": is not a function"); } // 調(diào)用bindFn方法的函數(shù)的引用 var self = this; // 以數(shù)組形式保存第二個(gè)及其以后的參數(shù) var beforeArg = [].slice.call(arguments,1); var bound = function() { // 以數(shù)組形式保存著當(dāng)前函數(shù)的所有參數(shù) var afterArg = [].slice.call(arguments); // bindFn第二個(gè)及其以后的參數(shù)和當(dāng)前函數(shù)所有參數(shù)的 集合 // 全部傳到self函數(shù)的參數(shù)里 var finalArgs = beforeArg.concat(afterArg); // 用new 方式調(diào)用 if(this instanceof bound) { // 避免es6箭頭函數(shù) // 箭頭函數(shù)沒有prototype if(self.prototype) { // 避免修改 bound.prototype 污染到 self.prototype function a(){} a.prototype=self.prototype; bound.prototype=new a(); bound.prototype.constructor=bound; } // self中的this指向 new生成的實(shí)例對(duì)象 return self.apply(this,finalArgs); } // 無new 調(diào)用方式, self中的this指向thisArg return self.apply(thisArg, finalArgs); } bound.prototype.getKey=function() { } return bound; }; var obj1={sex:23}; function m1(a,b) { this.name="m1"; console.log(a+b); // 6 console.log(this); } m1.prototype.allKey=function() { console.log("this is allkey"); } var bound=m1.bindFn(obj1,2); var result=new bound(4); result.allKey(); // 報(bào)錯(cuò) result.allKey is not a function
按理說 result原型鏈上應(yīng)該有allKey方法的,結(jié)果卻報(bào)錯(cuò)了,我們把m1中的this打印一下看看
這里我們看到原型鏈上并沒有m1.prototype, 所以在構(gòu)造函數(shù)內(nèi)部 完全重寫 構(gòu)造函數(shù)原型對(duì)象的話,原型鏈會(huì)與預(yù)想的不同。
那么圖上的bound.prototype打個(gè) ? ,因?yàn)椴⒉淮_定這個(gè)是bound.prototype,如果真是bound.prototype的話,那么下面的話如何解釋?
console.log(result.__proto__ === bound.prototype ) // false
按理說 result.__proto__ 指向的是bound.prototype,結(jié)果卻為false。所以不能肯定剛才的就是bound.prototype
總結(jié): 完全重寫構(gòu)造函數(shù)原型對(duì)象 要放在構(gòu)造函數(shù)后面,如果放在構(gòu)造函數(shù)里面,可能原型鏈會(huì)有錯(cuò)誤。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/99462.html
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對(duì)象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器,提供的值被忽略,同時(shí)調(diào)用時(shí)的參數(shù)被提供給模擬函數(shù)。 bind() bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù),當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),它的 this 值是傳遞給 bind() 的第一個(gè)參數(shù),傳入bind方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。bind返回的綁定函數(shù)也能使用 n...
摘要:但是三作為構(gòu)造函數(shù)時(shí)函數(shù)其實(shí)還有一個(gè)非常重要的特點(diǎn)返回的函數(shù)如果作為構(gòu)造函數(shù),搭配關(guān)鍵字出現(xiàn)的話,我們的綁定就需要被忽略。其次,當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)時(shí),之前綁定的會(huì)失效。 本文共 1100 字,讀完只需 4 分鐘 概述 前一篇文章我們嘗試模擬實(shí)現(xiàn)了 call 和 apply 方法,其實(shí) bind 函數(shù)也可以用來改變 this 的指向。bind 和 call和 apply 兩者的區(qū)別...
摘要:點(diǎn)擊那么面試官可能會(huì)問是否想過到底做了什么,怎么模擬實(shí)現(xiàn)呢。另外前不久寫過一篇文章面試官問能否模擬實(shí)現(xiàn)的操作符。所以相當(dāng)于調(diào)用時(shí),的返回值函數(shù)內(nèi)部要模擬實(shí)現(xiàn)實(shí)現(xiàn)的操作。文章中的例子和測(cè)試代碼放在中模擬實(shí)現(xiàn)。 前言 用過React的同學(xué)都知道,經(jīng)常會(huì)使用bind來綁定this。 import React, { Component } from react; class TodoItem ...
摘要:也就是說當(dāng)返回的函數(shù)作為構(gòu)造函數(shù)的時(shí)候,時(shí)指定的值會(huì)失效,但傳入的參數(shù)依然生效。構(gòu)造函數(shù)效果的優(yōu)化實(shí)現(xiàn)但是在這個(gè)寫法中,我們直接將,我們直接修改的時(shí)候,也會(huì)直接修改函數(shù)的。 JavaScript深入系列第十一篇,通過bind函數(shù)的模擬實(shí)現(xiàn),帶大家真正了解bind的特性 bind 一句話介紹 bind: bind() 方法會(huì)創(chuàng)建一個(gè)新函數(shù)。當(dāng)這個(gè)新函數(shù)被調(diào)用時(shí),bind() 的第一個(gè)參數(shù)...
摘要:大致就是這樣所以可以模擬實(shí)現(xiàn)和。這些參數(shù)作為的第二個(gè)參數(shù)跟在后面,之后它們會(huì)被插入到目標(biāo)函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會(huì)跟在它們的后面。 一個(gè)前端知識(shí)點(diǎn)匯總綜合了學(xué)習(xí)過程中的知識(shí)點(diǎn),比如this、閉包、BFC、ES6等,如果大佬們覺得還可以的話,求個(gè)star啦! call和apply 每個(gè)函數(shù)都包含兩個(gè)非繼承而來的方法:apply()和call() 用途相同,都是在...
摘要:模擬和模擬一樣,現(xiàn)摘抄下面的代碼添加一個(gè)返回值對(duì)象然后我們定義一個(gè)函數(shù),如果執(zhí)行下面的代碼能夠返回和函數(shù)一樣的值,就達(dá)到我們的目的。 原文:https://zhehuaxuan.github.io/... 作者:zhehuaxuan 目的 本文主要用于理解和掌握call,apply和bind的使用和原理,本文適用于對(duì)它們的用法不是很熟悉,或者想搞清楚它們?cè)淼耐? 好,那我們開始...
閱讀 3440·2021-09-26 09:46
閱讀 2788·2021-09-13 10:23
閱讀 3526·2021-09-07 10:24
閱讀 2396·2019-08-29 13:20
閱讀 2923·2019-08-28 17:57
閱讀 3078·2019-08-26 13:27
閱讀 1184·2019-08-26 12:09
閱讀 512·2019-08-26 10:27