this的理解相关

112 阅读1分钟
概念:this是执行上下文的一种属性,它指向最后一次调用的对象,this的指向是动态的,可以通过四种调用模式来判断。
1、函数调用模式;
    当函数不是一个对象的属性,直接调用时,this指向window;
2、方法调用模式;
    当函数作为一个对象的方法调用,this指向这个对象;
3、构造函数调用模式;
    通过new实例化对象调用,this指向这个新创建的对象。
4、call||apply||bind方法。
    fun.call(obj,1,2);
    fun.apply(obj,[1,2]);
    var test = fun.bind(o,1,2);
    test(3,4);
-----------------------------------------------------
优先级:new构造函数>call||apply||bind>对象方法>函数调用
-----------------------------------------------------
call和apply的区别:
    同:第一个参数代表函数体内的this指向;第一个参数为nullundefined的时候,默认指向window(严格模式下(`use strict`),函数体内的 this 还是为 null);传入false,this打印Boolean,数字打印number;
    异:call第二参数传参数列表,apply传数组集合;
-----------------------------------------------------
自定义实现call||apple||bind方法:

function test(a,b,c){
    console.log(this.name,a,b,c)
}
let obj_test = {name:'lalal'}

--------------------------------------
**call**:test.newCall(obj_test,1,2,3);

    Function.prototype.newCall = function (obj){
        if(typeof this !== 'function'){
            console.error("type error");
        }
        let result = null;//返回结果
        //(arguments 返回传入参数,第一位是传入的obj,所以截取,获取传入的参数)
        let args = [...arguments].slice(1);
        //判断是否传入正确的值
        obj = obj==undfind||obj==null?window:Object(obj);
        obj.fn = this;
        result = obj.fn(...args)
        delete obj.fn;
        return result;
    }
-----------------------------------------------------------
**apply**:test.newApply(obj_test,[1,2,3]);

Function.prototype.newApply = function(obj){
    if(typeof obj !== 'function'){
        console.error('erroe');
    }
    let result = null;
    //判断是否传入正确的值
    obj = obj==undfind||obj==null?window:Object(obj);
    obj.fn = this;
    result = arguments[1]?result.fn(...arguments[1]):result.fn();
    delete obj.fn;
    return result;
}
-----------------------------------------------------------
**bind**:test.newBind(obj_test)();

Function.prototype.newBind = function(obj){
    if(typeof obj !== 'function'){
        console.error('erroe');
    }
    
    let that = this;
        arg = [...arguments].slice(1);//截取this,获取参数
    return function Fn(){
        //this instanceof Fn 判断对象是普通调用还是new 调用
        return that.apply(
            this instanceof Fn?this:obj,
            arg.concat(...arguments)
        )
    }
}