call
实现原理:
把方法绑定到目标对象上,然后执行,执行完毕后在目标对象上删除
// call的实现原理是把方法绑定到目标对象上,借过来用,用完之后然后删除
Function.prototype._call = function(target, ...args){
// 判断调用对象是不是函数
if(typeof this !== "function"){
throw new TypeError('error');
}
target = target || window;
const key = Symbol('fn');
target[key] = this;
const res = target[key](...args);
delete target[key];
return res;
}
const B = {
name: 'B',
say(prefix, age) {
console.log(`${prefix},my name is ${this.name},i am ${age} year old`)
}
}
const A = {
name:'小A'
}
B.say._call(A,'hello',3) // 'hello,my name is A,i am 3 year old'
apply
apply原理和call一样,区别在于传参方式不同,call是一个一个参数传递(obj, arg1, arg2…),而apply是将参数放在数组中传递(obj, [arg1, arg2…])
Function.prototype._apply = function(target, args){
// 判断调用对象是不是函数
if(typeof this !== "function"){
throw new TypeError('error');
}
target = target || window;
const key = Symbol('fn');
target[key] = this;
const res = target[key](...args);
delete target[key];
return res;
}
const B = {
name: 'B',
say(prefix, age) {
console.log(`${prefix},my name is ${this.name},i am ${age} year old`)
}
}
const A = {
name:'小A'
}
B.say._apply(A,'hello', 3) // 'hello,my name is A,i am 3 year old'
bind函数
bind函数和call函数传参方式一样,但是bind函数并不会直接执行,而是将函数返回过来
// 自定义简陋版bind方法实现
Function.prototype._bind = function(context, ...args) {
// 判断调用对象是不是函数
if(typeof this !== "function"){
throw new TypeError('error');
}
// 如果没有传入上下文对象,则默认为全局对象window
context = context || window
// 保存原始函数的引用,this就是要绑定的函数
const _this = this
// 返回一个新的函数作为绑定函数
return function fn(...innerArgs) {
// 判断返回出去的函数有没有被new,如果是new出来的,不给this作用域
if(this instanceof fn){
return new _this(...args, ...innerArgs);
}
// 使用 apply 方法将原函数绑定到指定的上下文对象上
return _this.apply(context, [...args, ...innerArgs]);
};
};
function foo(x, y, z) {
this.name = "张三";
console.log(this.num, x + y + z);
console.log(this.name);
}
var obj = {
num: 666
}
var foo2 = foo._bind(obj, 1,2,3);
console.log(new foo2);