call
fun.call(thisArg, arg1, arg2, …)
Function.prototype.myCall = function (obj, ...rest) {
var context = obj || window;
context.fn = this;
var result = context.fn(...rest);
delete context.fn;
return result;
}
apply
func.apply(thisArg, [argsArray])
Function.prototype.myApply = function (obj, rest) {
var context = obj || window;
context.fn = this;
var result = context.fn(...rest);
delete context.fn;
return result;
}
bind
fun.call(thisArg, arg1, arg2, …)
返回一个原函数的拷贝,并拥有指定的this值和初始参数。
只有参数列表会叠加
Function.prototype.myBind = function (obj, ...rest) {
var context = obj || window;
context.fn= this;
return function() {
var result = context.fn(...rest, ...arguments);
delete context.fn;
return result;
}
}
let obj = {
name: "lala",
age: this.age,
show: function() {
console.log(this.name, this.age);
return [...arguments].reduce((a,b) => {
return a+b;
}, 0)
}
}
obj.show();
obj.show.myCall({name: "nene", age: 12}, 1,2,3,4);
obj.show.myApply({name: "nene", age: 12}, [1,2,3,4]);
obj.show.myBind({name: "nene", age: 12}, 1,2,3,4)(5,6);
依赖call || apply实现(参数处理的不同啦)
Function.prototype.myBind = function (obj, ...rest) {
const self = this;
const context = obj || window;
return function() {
return self.call(obj, ...rest, ...arguments);
}
}
考虑bind返回的函数用作构造函数
Function.prototype.myBind = function (obj, ...rest) {
var self = this;
const context = obj || window;
return function F() {
if (this instanceof F) {
return new self(...rest, ...arguments);
}
return self.call(context, ...rest, ...arguments);
}
}
es5
function bind(obj) {
if (typeof obj === "object") {
obj = obj || window;
} else {
obj = Object.create(null);
}
let rest = [];
// call, bind
for(let i = 1; i < arguments.length; i++) {
rest.push(arguments[i]);
}
let self = this;
let F = function() {};
let bound = function () {
let finalArgs = [...rest, ...arguments];
let result = self.call((this instanceof F ? this : obj), ...finalArgs);
return result;
};
F.prototype = self.prototype;
bound.prototype = new F();
return bound;
}
new func('4th'); //undefined 100 1st 4th
// 从 ES5 的 bind 函数说明中我们知道,当我们用一个函数调用 bind 的时候,
// 返回的函数中会保存这三个参数。所以最后调用 call 的时候执行的函数是目标函数,
// 也就是调用了 bind 的函数,传入的 this 也是 bind 调用时传入的,这些都是无法被修改的了,
// 但是参数是调用 bind 和 call 时的叠加,这是我们唯一可以修改的地方。
// 执行两次 bind 的原理可以参考 bind 的源码,和 call 的差不多,也是目标函数和 this 是被固定的了,只有参数列表会叠加