成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手寫 Bind:處理 New 的情況

開發 前端
因為很少會遇到給 Bind 返回的函數做 New 操作的場景,所以我沒去考慮這種特殊情況。但面試中還是會涉及到的,我們還是實現一下兼容 New 操作的 Bind 寫法,順便學習一下 New 操作符。

大家好,我是前端西瓜哥。

之前寫了一篇關于?? JS 中 bind 方法的實現??的文章,并給出了實現:

Function.prototype.myBind = function(thisArg, ...prefixArgs) {
const fn = this;
return function(...args) {
return fn.call(thisArg, ...prefixArgs, ...args);
}
}

但沒有處理 通過 new 創建實例 的情況。

因為很少會遇到給 bind 返回的函數做 new 操作的場景,所以我沒去考慮這種特殊情況。

但面試中還是會涉及到的,我們還是實現一下兼容 new 操作的 bind 寫法,順便學習一下 new 操作符。

因為存在一定上下文,在閱讀本文前,建議先閱讀前一篇文章:《??前端面試題:手寫 bind??》。

new

我們先學習一下 new 操作符。

new 用于通過函數來創建一個對象實例,在很多語言中都能看到。

JS 的函數,除了可以是普通函數,比如:

function sum(a, b) {
return a + b;
}

還可以是構造函數,只需要在構造時在它前面加一個 new:

function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person('前端西瓜哥', 100)
// Person {name: '前端西瓜哥', age: 100}

new 創建一個新對象,做了下面幾件事:

  1. 創建一個空對象 {}。
  2. 空對象的原型屬性 __proto__指向構造函數的原型對象Person.prototype。
  3. 函數中的 this 設置為這個空對象。
  4. 如果該函數不返回一個對象,就返回這個 this,否則返回這個對象。

判斷函數是否通過 new 被調用

怎么判斷一個函數正在被 new 操作符調用?

?答案是 使用 instanceof 判斷 this 是否為當前函數的實例,即 this instanceof Fn 為 true,表示在通過 new 構建實例。

我們看一個例子:?

function Person() {
if (this instanceof Person) {
console.log('通過 new 構建實例');
} else {
console.log('普通調用')
}
}
Person() // 輸出:普通調用
new Person() // 輸出:通過 new 構建實例

在 Vuejs 的源碼,你會看到下面代碼,這里也用到了這個技巧。

function Vue(options) {
if (__DEV__ && !(this instanceof Vue)) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}

你在開發環境如果不通過 new 來使用 Vue 對象,會在控制臺提示你要通過 new 來調用 Vue。

new 和 bind

如果我們 new 的是 Function.prototype.bind 返回的新函數,會發生什么事情?

function Person(name, age) {
this.name = name;
this.age = age;
}
const BoundPerson = Person.bind(null, '前端西瓜哥');
const boundPerson = new BoundPerson(100);
// Person {name: '前端西瓜哥', age: 100}
boundPerson.__proto__ === Person.prototype
// true

結果等價于直接去 new 原始函數。

不同的是,仍舊可以進行參數的預置??梢钥吹?,構造函數的第一個參數,在調用 bind 的時候就提前設置為 '前端西瓜哥'。

實現完整的 bind

完整實現如下:

Function.prototype.myBind = function(thisArg, ...prefixArgs) {
const fn = this;
const boundFn = function(...args) {
// 通過 new 使用當前函數
if (this instanceof boundFn) {
return new fn(...prefixArgs, ...args);
}
// 普通的方法調用當前函數
return fn.call(thisArg, ...prefixArgs, ...args);
}
boundFn.prototype = fn.prototype;
return boundFn;
}

這里我通過 this instanceof boundFn 來判斷是否用了 new,如果是,就直接 new 原始函數然后返回,記得帶上 bind 預置好的參數。

其他保持原樣(具體見上文??《前端面試題:手寫 bind》??)

boundFn.prototype = fn.prototype; 這個可寫可不寫,只是讓 bind 返回的新函數的 prototype 指向原函數的 prototype。

如果是原生 bind 返回的函數,它是沒有 protoype 屬性的,可以認為它是一種特別的函數,而我們實現的 bind 返回的卻是一個普通函數,所以并不能完全模擬的。

如果你 追求完美的實現,可以研讀一下 Function.prototype.bind 的標準:

https://tc39.es/ecma262/#sec-function.prototype.bind。

然后再看看知名的 core.js 庫中對 bind 的實現:

https://github.com/zloirock/core-js/blob/cafe9ecf2b384385f8b8d1da0047e44586fff2dc/packages/core-js/internals/function-bind.js#L23-L33。

其中核心實現為:

// `Function.prototype.bind` method implementation
// https://tc39.es/ecma262/#sec-function.prototype.bind
module.exports = Function.bind || function bind(that /* , ...args */) {
var F = aCallable(this);
var Prototype = F.prototype;
var partArgs = arraySlice(arguments, 1);
var boundFunction = function bound(/* args... */) {
var args = concat(partArgs, arraySlice(arguments));
return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
};
if (isObject(Prototype)) boundFunction.prototype = Prototype;
return boundFunction;
};

這里有更多的細節:

  • 這里判斷了 this 是否為函數類型,不是函數會報錯。
  • F.prototype 需要是一個對象或函數,才能賦值給新函數。
  • 使用了普通函數和 arguments,這是為了兼容 ES5。

結尾

手寫 bind,現在想來并不簡單,需要掌握好很多知識點:

  • bind 的詳盡用法:包括改變 this、預置參數、new 的表現。
  • 閉包的使用:保存一些私有變量。
  • 通過原型鏈的方式(this instanceof boundFn)判斷是否通過 new 調用當前函數。
  • 使用 call 在執行時改變函數的 this 指向。
責任編輯:姜華 來源: 今日頭條
相關推薦

2021-12-01 06:40:32

Bind原理實現

2021-12-05 08:27:56

Javascript 高階函數前端

2024-03-15 08:21:17

bindJavaScrip函數

2010-06-23 15:16:40

Linux Bash

2020-11-24 12:10:22

瀏覽器前端斷網

2021-08-18 08:20:14

SQL除數統計

2021-10-29 08:07:30

Java timeout Java 基礎

2021-09-26 05:05:09

WindowWeb JS

2010-04-12 14:44:22

Linux系統

2011-08-25 13:58:08

bind中文man

2020-09-18 10:31:47

LRU算法數組

2020-10-10 07:00:16

LinuxSocketTCP

2011-03-17 15:48:32

jQuery

2016-11-10 17:03:50

商用電腦

2013-03-01 11:17:38

BIND10DNS

2010-03-08 08:39:54

類加載器newJava

2024-08-26 14:35:19

JavaScript關鍵字對象

2009-12-21 17:18:45

Linux操作系統

2011-11-30 13:29:46

2020-11-02 09:35:04

ReactHook
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 永久免费视频 | h视频在线观看免费 | 午夜激情国产 | 亚洲精品中文在线观看 | 中国一级特黄真人毛片免费观看 | 99精品国产一区二区青青牛奶 | 在线一区视频 | av手机免费在线观看 | 日本亚洲一区 | 精品欧美一区二区精品久久久 | 国产精品久久久久9999鸭 | 久久99精品久久久久久秒播九色 | 一级黄色片网址 | 亚洲欧美一区二区三区1000 | 天天色官网 | 黄色毛片在线观看 | 天天艹 | 色视频欧美 | 成人久久久久久久久 | 国产精品久久久久免费 | 天天综合久久 | 欧美成人精品欧美一级 | 国产一区二区三区精品久久久 | 亚洲免费高清 | 亚洲欧美在线视频 | 成人影音 | 逼逼网 | 亚洲欧美成人影院 | 亚洲国产视频一区二区 | 99精品国产一区二区青青牛奶 | 天天操天天拍 | 成人久久久 | 中文字幕一区在线观看视频 | 久久久国产一区二区三区 | 日韩在线播放中文字幕 | 成人在线观看网址 | 在线播放国产一区二区三区 | 成人免费视频一区二区 | 亚洲国产91 | 成人依人 | 九九热久久免费视频 |