原生JS重寫Function.prototype.bind( )方法
阿新 • • 發佈:2021-02-08
技術標籤:JS面試JavaScriptjsjavascriptbind
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
< body>
<script>
Function.prototype.myBind = function (context) {
// fn.bind(obj) fn必須為函式,否則會報錯
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this ; // 這裡的this是呼叫bind()方法的函式(fn),儲存給 self
var args = Array.prototype.slice.call(arguments, 1); // 獲取 myBind函式 從第二個引數到最後一個引數
var fNOP = function () {}; // 使用聖盃模式來繼承時的中間函式
var fbound = function () {
// 當作為建構函式時,this 指向例項,self 指向繫結函式,因為下面一句 `fbound.prototype = this.prototype;`,已經修改了 fbound.prototype 為 繫結函式的 prototype,此時結果為 true,當結果為 true 的時候,this 指向例項。
// 當作為普通函式時,this 指向 window,self 指向繫結函式,此時結果為 false,當結果為 false 的時候,this 指向繫結的 context。
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
// 上面的 arguments 是 fbound函式(返回的新函式) 的實參
}
fNOP.prototype = self.prototype;
fbound.prototype = new fNOP();
return fbound;
}
// 測試重寫後的效果
var value = 2;
var foo = {
value: 1
};
function bar(name, age) {
this.habit = 'shopping';
console.log(this.value);
console.log(name);
console.log(age);
}
bar.prototype.friend = 'kevin';
var bindFoo = bar.bind(foo, 'daisy');
var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit); // shopping
console.log(obj.friend); // kevin
console.log(obj);
</script>
</body>
</html>