call实现
1. 给函数的原型中添加方法
Function.prototype.mycall = function() {
console.log(123);
}
function num() {
console.log('测试创建的函数是否包含mycall的方法');
}
function foo() {
console.log('测试创建的函数是否包含mycall的方法');
}
num.mycall() //123
foo.mycall() //123
2. mycall函数中获取当前调用的方法,(Fn.mycall)调用的方法是隐式绑定,所以直接使用this就可以获取了
Function.prototype.mycall = function() {
console.log(this);
}
...
...
num.mycall() //[Function: num]
foo.mycall() //[Function: foo]
3. 此时函数已经拿到了后面只需要修改它的this指向就可以了,既然上面已经确定了是隐式绑定那只需要修改"."前面的参数就可以实现动态绑定this了。
Function.prototype.mycall = function(thisArg) {
let fn = this
thisArg.fn = fn;
thisArg.fn();
}
function num() {
console.log(this);
}
function foo() {
console.log(this);
}
num.mycall({}) //{ fn: [Function: num] }
foo.mycall([123]) //[ 123, fn: [Function: foo] ]
4. 现在基本的this自定义绑定已经实现了,但是还有三个大的问题。
- thisArg.fn = fn;这段代码给this增加了fn函数(调用mycall的函数)。
- 当传入非对象类型无法绑定为this。
- 无法传人参数
Function.prototype.mycall = function(thisArg = window, ...args) { //获取自定义this及参数
let fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window; //对传人的this做对象转化,为null或者undefined改为window,
thisArg.fn = fn;
let result = thisArg.fn(...args);
delete thisArg.fn //删除fn
return result //返回函数
}
function num() {
console.log(this);
}
function foo() {
console.log(this);
}
num.mycall({})
foo.mycall(123)
apply实现
Function.prototype.mycall = function (thisArg = window, args = []) { //获取自定义this及参数
let fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window; //对传人的this做对象转化,为null或者unified改为window,
thisArg.fn = fn;
if (!(args instanceof Array)) throw new SyntaxError("传入的参数类型不是数组"); //确保参数为数组类型
let result = thisArg.fn(...args);
delete thisArg.fn //删除fn
return result //返回函数
}
function num() {
console.log(this);
}
function foo(str) {
console.log(this, str);
}
num.mycall({}, [])
foo.mycall('aaa', ['pxq'])
bind的实现
Function.prototype.mybind = function (thisArg = window, ...args) { //获取自定义this及参数
let fn = this;
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;
return function(...argsArray) {
thisArg.fn = fn
let result = thisArg.fn(...args, ...argsArray);
delete thisArg.fn
return result
}
}
function num (num1, num2) {
console.log(this, num1, num2);
}
function foo () {
console.log(this);
}
var newNum = num.mybind({}, 10)
newNum(20)
var newFoo = foo.mybind([]);
newFoo()