手写call apply bind

这个笔记是自己练习时的记录,仅供参考

1.call

Function.prototype.mycall = function(context,...args){
    //验证context是否存在,不存在指向window
    let ctx = context || window;
    //判断args是否存在,不存在赋值为空数组
    args = args?args:[]
    //在指定的上下文中加一个新的属性方法并将参数传递进去,最后执行
    let func = Symbol(); // 确保这个属性是唯一的
    ctx[func] = this; //将调用mycall的方法定义在ctx[func]上
    let result = ctx[func](...args); //以对象形式调用this,这个时候方法的this指向ctx
    delete ctx[func];//删除这个方法,避免对传入的对象造成污染,添加了这个方法
    return result;
}
function a(...params){
    console.log(this.scope+":"+params);
}
var b = {
    scope:"bObject"
};
a.mycall(b,1,2);
a.call(b,1,2,3);
console.log(b);

执行结果:


result.png

2.apply

Function.prototype.myapply = function(context,args){
    //验证context是否存在,不存在则绑定到window
    let ctx = context || window;
    //判断args是否为空
    args = args ? args:[];
    //声明一个唯一的值
    let func =Symbol();
    ctx[func] = this; // 将调用myapply的函数绑定到属性func上
    let res = ctx[func](args); //这里func函数执行的this就在ctx上
    delete ctx[func];
    return res;
}
function testApply(params){
    console.log(this.scope1+":"+params)
}
var c ={
    scope1:"cObject"
};
testApply.myapply(c,[1,2,3]);
testApply.apply(c,[1,2,3]);
console.log(c);

执行结果:


result1.png

3.bind

Function.prototype.mybind = function (context, ...args) {
    let ctx = context || window;
    args = args ? args : [];
    let func = this; // 这个this指的是调用mybind的函数,将它先存起来
    //返回值是一个函数,这个函数的this已经指向了ctx
    return function newFun(...newFunArgs) {
        //当返回的这个函数作为构造函数的时候,进行原型继承
        if (this instanceof newFun) {
            return new func(...args, ...newFunArgs);
        }
        return func.myapply(ctx, [...args, ...newFunArgs]);
    }
}
function a(...params) {
    console.log(this.scope + ":" + params);
}
var b = {
    scope: "bObject"
};
const z = a.mybind(b, 1, 2);
console.log(z);
//如果将bind后的新函数使用new,this会改变,
const w = new z();
console.log(w);

执行结果:
result2.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容