call
改变this指向,带参数调用一个函数。
所以要实现:
- call改变this的指向,指向到第一个参数
- 函数要执行
- 可以传递多个参数
- 参数可以为null
- 要有返回值
模拟实现
Function.prototype.call2 = function(context) {
//当第一个参数是null时,就会将this指向window
context = context || window;
//把函数绑到指向的对象上去
context.fn = this;
let args = [];
//制造一个arguments[1],arguments[2]这样的数组
for (let i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
//使用eval,并把arguments传入函数去执行
let result = eval('context.fn(' + args + ')');
//把方法从指向的对象上删除
delete context.fn;
//返回值
return result;
};
var value =1
var foo = {
value: 1
};
console.log(bar.call2(null));
function bar(name, age) {
return {
value: this.value,
name,
age
};
}
console.log(bar.call2(foo, 'will', 18));
apply
同样是改变this指向,但是后面参数是数组形式
模拟实现
Function.prototype.apply2 = 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
bind()会创建一个新函数。当新函数被调用时,bind的第一个参数作为运行时的this,之后的一序列参数会做为它的参数。
var foo = {
value: 1
};
function bar(name, age) {
console.log(this.value);
console.log(name);
console.log(age);
}
var bindFoo = bar.bind(foo, 'daisy');
bindFoo('18');
// 1
// daisy
// 18
函数需要传 name 和 age 两个参数,竟然还可以在 bind 的时候,只传一个 name,在执行返回的函数的时候,再传另一个参数 age!