call 是改变了 this 的指向的。
this的意思是谁调用指向谁 理解一下这句话。
var foo = {
value: 1,
bar: function() {
console.log(this.value)
}
};
// foo这个对象调用了bar函数,
// 那么bar函数里面的this指向的是foo对象
foo.bar();
直接上最终代码:
Function.prototype.mycall = function(context) {
var context = context || window;
context.fn = this; // this 指的就是 foo函数
var args = [];
for(var i = 1,len=arguments.length; i < len; i++){
args.push('arguments[' + i +']'); // foo.call(obj , 'john', 'M') 第一个参数不需要加入,循环从1开始。
}
var result = eval('context.fn('+ args +')' )// 利用eval来执行,因为参数是动态的。
delete context.fn;
return result
}
// 使用方法:
function foo(sex,age){
console.log(this.name); // obj 的name
this.sex = sex;
this.age = age;
console.log(sex,age);
}
var obj = {name: 'mike'};
foo.mycall(obj,'M',18);
apply 模拟实现
和call的区别就是参数是数组形式。
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')')
}
delete context.fn
return result;
}
bind 模拟:
Function.prototype.bind2 = function (context) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fbound = function () {
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
}
fNOP.prototype = this.prototype;
fbound.prototype = new fNOP();
return fbound;
}
参考: https://juejin.im/post/5907eb99570c3500582ca23c
https://juejin.im/post/59093b1fa0bb9f006517b906