call
call() 方法調(diào)用一個(gè)函數(shù), 其具有一個(gè)指定的this值和分別地提供的參數(shù)(參數(shù)的列表)每篷。
例如:
var foo = { x: 10 };
function test(y) {
console.log(this.x,y);
}
test.call(foo,20); //10 20
- 為達(dá)到綁定this的效果喜每,可以將函數(shù)加到傳入的對(duì)象上進(jìn)行調(diào)用。
Function.prototype.call2 = function (self) {
self.fn = this;
return self.fn();
}
但這樣傳入的對(duì)象就多了一個(gè)屬性了
- 在調(diào)用后刪除掉這個(gè)屬性
Function.prototype.call2 = function (self) {
self.fn = this;
var result = self.fn();
delete self.fn();
return result;
}
- 將提供的參數(shù)傳入
Function.prototype.call2 = function (self) {
self.fn = this;
var params = [];
for (var i = 1; i < arguments.length; i++) {
params.push(`arguments[` + i + `]`);
}
var result = eval('self.fn(' + params + ')');
delete self.fn;
return result;
}
- 當(dāng)傳入對(duì)象為空時(shí)雳攘,this綁定到window
Function.prototype.call2 = function (self) {
self = self || window;
self.fn = this;
var params = [];
for (var i = 1; i < arguments.length; i++) {
params.push(`arguments[` + i + `]`);
}
var result = eval('self.fn(' + params + ')');
delete self.fn;
return result;
}
apply
與call類似带兜,區(qū)別時(shí)apply傳入的參數(shù)列表為數(shù)組
Function.prototype.apply2 = function (self, args) {
self = self || window;
self.fn = this;
var result;
if (!args || !args.length) {
result = self.fn();
} else {
var params = [];
for (var i = 0; i < args.length; i++) {
params.push(`args[` + i + `]`);
}
result = eval('self.fn(' + params + ')');
}
delete self.fn;
return result;
}
bind
- bind會(huì)返回一個(gè)函數(shù),該函數(shù)的this綁定到第一個(gè)參數(shù)上吨灭。
Function.prototype.bind2 = function (self) {
var fn = this;
return function () {
return fn.apply(self);
}
}
- bind返回的函數(shù)可以接收參數(shù)
Function.prototype.bind2 = function (self) {
var fn = this;
return function () {
var bindArgs = Array.prototype.slice.call(arguments);
return fn.apply(self,bindArgs);
}
}
- 調(diào)用bind的時(shí)候可以先綁定一部分參數(shù)刚照,在調(diào)用其返回的函數(shù)時(shí)傳入的參數(shù)會(huì)跟在bind綁定的那部分參數(shù)后面
Function.prototype.bind2 = function (self) {
var fn = this;
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var bindArgs = Array.prototype.slice.call(arguments);
return fn.apply(self, args.concat(bindArgs));
}
}
- 對(duì)bind返回的新函數(shù)進(jìn)行構(gòu)造調(diào)用時(shí),this綁定到新構(gòu)造的對(duì)象上喧兄,而非bind綁定的對(duì)象无畔。
Function.prototype.bind2 = function (self) {
var fn = this;
var args = Array.prototype.slice.call(arguments, 1);
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
//如果this是此函數(shù)的實(shí)例,證明是被構(gòu)造調(diào)用了吠冤,此時(shí)綁定新構(gòu)造的對(duì)象
return fn.apply( this instanceof fBound ? this : self, args.concat(bindArgs));
}
return fBound;
}
- 維護(hù)原型關(guān)系浑彰,否則會(huì)有這樣的問題
function Test(){}
var t = Test.bind({});
var o = new t();
o instanceof Test // false
Function.prototype.bind2 = function (self) {
var fn = this;
var args = Array.prototype.slice.call(arguments, 1);
var f = function(){};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return fn.apply(this instanceof fBound ? this : self, args.concat(bindArgs));
}
if(this.prototype){
f.prototype = fn.prototype;
}
fBound.prototype = new f();
return fBound;
}
6.調(diào)用bind的不是函數(shù)要報(bào)錯(cuò)
if (typeof this !== "function") {//加上判斷
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}