关于js 中的this

2019-07-24  本文已影响0人  aibinMr
        var name='小张',
        age=17;
        var obj={
            name:'小刘',
            objAge:this.age,
            myFun:function(){
                console.log(this.name+'年龄'+this.age);
                console.log('查看对象内'+this.objAge)
            }
        }
        obj.myFun()
        //小刘年龄undefined
        //查看对象内17
        var db={
            name:'德玛',
            age:99
        }
        var db2={
            name:'伽罗',
        }
        obj.myFun();
        obj.myFun.call();//小张年龄17 此时this指向window
        obj.myFun.call(db);//德玛年龄99
        obj.myFun.call(db2);//伽罗年龄undefined 说明传入对象替换了this,
        obj.myFun.apply(db);//德玛年龄99
        obj.myFun.bind(db)();//德玛年龄99---->bind 返回的是函数,必需调用执行
        var obj2={
            name:'小刘',
            objAge:this.age,
            myFun:function(fm,t){
                console.log(this.name+'年龄'+this.age,'来自'+fm+'去往'+t);
            }
        }
        //call、 bind、 apply 这三个函数的第一个参数都是this的指向对象
        //|->call可以传入多个参数,多个参数逗号隔开
        obj2.myFun.call(db,'江西','深圳');//德玛年龄99 来自江西去往深圳
        //|->apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入
        obj2.myFun.apply(db,['江西','深圳']);//德玛年龄99 来自江西去往深圳
        //|->bind除了返回函数以外,它的参数和call 一样
        obj2.myFun.bind(db,'江西','深圳')();//德玛年龄99 来自江西去往深圳
        //|->此处测试是吧'江西,深圳'作为一个数组传进去,所以参数fm就是'江西,深圳',中间的逗号应该是数组转义的时候产生的
        obj2.myFun.bind(db,['江西','深圳'])();//德玛年龄99 来自江西,深圳去往undefined

        function fun1() {
            this.ccfun1='命名函数_1';
            return this 
        }
        function fun2() {
            this.ccfun2='命名函数_2'    
        }
        let unnameFun1=function(){
            this.ccunnameFun1='匿名函数_return this 1'
            return this 
        }
        let unnameFun2=function(){
            this.ccunnameFun2='匿名函数_2 un return'    
        }
        
        let arrowFun1=()=>{
            this.ccarrow1 ='箭头函数_1';
            debugger
            return this     
        }
        let arrowFun2=function(){
            this.ccarrow2 ='箭头函数__2'
            
        }
        //测试命名函数
        console.log('----------return this;new----------')
        // 带this返回
        var fun1_new=new fun1();
        console.log(fun1_new.ccfun1)//命名函数_1  返回的this中绑定了指定变量
        console.log(window.ccfun1)//undefined  此变了未绑定在window上 说明函数创建的时候 this是函数内部的this,或者调用者非window
        console.log('----------return this;un new----------')
        var fun1_unnew=fun1();
        console.log(fun1_unnew===window) //true 此处证明 直接调用函数,不使用new创建,函数内部的this指向window
        console.log(window.ccfun1) //命名函数_1
        console.log('----------unreturn this;new----------')
        var fun2_new=new fun2();
        console.log(fun2_new.ccfun2)//命名函数_2  此处证明 return this不重要可以省略
        console.log(window.ccfun2)//undefined  
        var fun2_unnew=fun2();
        console.log(fun2_unnew===window) //此处证明 在不使用new 和return的情况 返回值既不是函数调用者也不是window
        console.log(fun2_unnew) //undefined 此处证明 直接调用函数,不适用new创建,函数内部的
        console.log(window.ccfun2) //命名函数_2

        /*  总结 命名函数
            1:new 一定会有返回 返回值是其调用者
            var fun1_new=new fun1() <==> var fun1_new=new fun1(this:fun1_new);
            2:直接调用函数,函数内部的this会指向window 此时return 决定是否有返回
            var fun1_new=fun1() <==> var fun1_new=fun1(this:window);
        */

        //测试匿名函数
        console.log('------匿名函数----return this;new----------')
        // 带this返回
        var unnameFun1_new=new unnameFun1();
        console.log(unnameFun1_new.ccunnameFun1)//匿名函数_return this 1  同上命名函数测试
        console.log(window.ccunnameFun1)//undefined  同上命名函数
        console.log('----------return this;un new----------')
        var unnameFun1_unnew=unnameFun1();
        console.log(unnameFun1_unnew===window) //true 此处证明 直接调用函数,不使用new创建,函数内部的this指向window
        console.log(unnameFun1_unnew.ccunnameFun1) //命名匿名函数_return this 1函数_1
        console.log('----------unreturn this;new----------')
        var unnameFun2_new=new unnameFun2();
        console.log(unnameFun2_new.ccunnameFun2)//命名函数_2  此处证明 return this不重要可以省略
        console.log(window.ccunnameFun2)//undefined  
        var unnameFun2_unnew=unnameFun2();
        console.log(unnameFun2_unnew===window) //此处证明 在不使用new 和return的情况 返回值既不是函数调用者也不是window
        console.log(unnameFun2_unnew) //undefined 此处证明 直接调用函数,不适用new创建,函数内部的
        console.log(window.ccunnameFun2) //命名函数_2

        /*  总结 匿名函数
            1:new 一定会有返回 返回值是其调用者
            var fun1_new=new fun1() <==> var fun1_new=new fun1(this:fun1_new);
            2:直接调用函数,函数内部的this会指向window 此时return 决定是否有返回
            var fun1_new=fun1() <==> var fun1_new=fun1(this:window);
        */
        console.log('------箭头函数----return this;new----------')
        //let arrowFun1_new = new arrowFun1();
        //console.log(arrowFun1_new.ccarrow1)//error 箭头函数不能new 使用
        let arrowFun1_unnew=arrowFun1();
        console.log(arrowFun1_unnew.ccarrow1)//error 箭头函数不能new 使用
        console.log(window==arrowFun1_unnew)//true  箭头函数内部使用this==window
        let arrowFun2_unnew=arrowFun2();
        console.log(window==arrowFun2_unnew)//false  箭头函数是否有返回值由return决定
            总结 一  命名函数 和 匿名函数 中的this
                1 函数中的this由调用者决定 new创建的函数 函数的调用者是创建函数的变量,非new方法调用函数 函数的调用者将是window
                2 new 和 return同时决定是否产生返回值,new决定由返回值的优先级高于return ,在不存在new的情况下 由return决定
                3 如果想通过创建者调用函数内部参数及方法 应该在函数内部使用'this.xxx'进行绑定

                二 箭头函数
                1 箭头函数不能使用new 创建函数实例
                2 箭头函数是否有返回值由return决定
                3 箭头函数内的this指向window
                三 call,apply,bind中的this             
                  这三个函数作用就是更改调用者中this的指向,很多教程介绍是传入对象调用调用者
中函数,有点拗口和不好理解,这种说法把传入对象当成主体和执行者,有点类似于你请鲍鱼,你是原对象,
请吃鲍鱼是执行方法,鲍鱼是方法中this绑定的喜欢的吃食物,现在通过call,apply,bind绑定对象,
这个对象用同事表示,同事喜欢吃的是龙虾,绑定之后的结果就变成你请吃龙虾,同事喜欢吃的食物替换
请吃方法中的this绑定的食物,这个过程顺序说法是你请吃的朋友喜欢的龙虾,逆序说法是朋友让你请
吃的东西是朋友喜欢的龙虾。理解起来有点绕,而我个人理解的就是我请吃东西 ,具体
是什么东西,由我调用的对象决定,类似于obj2.myFun.call(db,'江西','深圳')中,db是被
调用的对象,db对象替换了调用方法中的this,如果偏要解释成db对象调用了调用者的方
法,两个的效果是一样的,执行的方法是同一个,this都是传入对象,如果方法中this的
属性在传入对象中不存在,则这个属性为undefind。
                    
              1 传入对象替换执行方法中的this
              2 方法中的this是替换,不是深度复制
              3 在没有传入对象的时候 ,执行方法中的this指向window
                

                四 扩展 如果单纯想通过返回值调用调用原函数方法 可以通过原型绑定
                    function Person(first, last, eye) {
                        this.firstName = first;
                        this.lastName = last;
                        this.eyeColor = eye;
                    }

                    Person.prototype.age=function(age){
                        this._age=age;
                    };
                    var p1 = new Person("John", "Doe", "blue");
                        p1.age(20);
                    var p2 = new Person("li", "li", "black");
                        p2.age(15);
                    console.log(p1._age) //20
                    console.log(p2._age) //12   

                    age();方法内的this执行被创建的对象      
            
上一篇 下一篇

猜你喜欢

热点阅读