把我搞晕的this----希望把你也搞晕

1.先做题看看自己有啥问题---先做再跑哈

第零题

        let name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        let f=obj.func;
        f();
复制代码

第一题

        let name="window"
        let obj={
            name:"zhangsan",
            func:function(){
                console.log(this.name);
            }
        }
        let f=obj.func;
        f();
复制代码

第二题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        let f=obj.func;
        f();
复制代码

第三题

         var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        obj.func();
复制代码

第四题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        let f=obj.func;
        f.apply(obj);
复制代码

第五题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        let f=obj.func;
        f.call(obj);
复制代码

第六题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);
            }
        }
        let f=obj.func;
        f.bind(obj);
复制代码

第七题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);
                return s;
            }
        };
        let f = obj.func;
        let func=f();
        func();
复制代码

第八题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);
                return s;
            }
        };
        let f = obj.func();
        f();
复制代码

第九题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);
                return s;
            }
        };
        let f = obj.func();
        let B={
               name:"lisi"
        }
        f.call(B);
复制代码

第十题

    var length = 10;
    let fn = () => {
        console.log(this.length);
    }
    var obj = {
        length: 5,
        method: function(fn) {
            fn();
            arguments[0]();
        },
    };
    obj.method(fn, 1);
复制代码

2.答案解释

第零题

        let name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//undefined
            }
        }
        let f=obj.func;
        f();
复制代码

类中的方法中this的指向由其调用对象决定,本题中最终执行时候是直接调用的,所以指向全局的window对象,那为什么不是输出window呢,哦原来是let声明的(var声明的和函数声明才会变成window的属性)。

第一题

        let name="window"
        let obj={
            name:"zhangsan",
            func:function(){
                console.log(this.name);//name
            }
        }
        let f=obj.func;
        f();
复制代码

这题就是坑人,name虽然不是关键字也不是保留字,但它是属性,不能作为变量名,类似的有toplocationself,但leftbottom却可以,原因是这些变量名是JS的主机变量,永远不能被重新声明,带上链接这就说明在平时变量命名时候要遵循一定的规范呀,要不然这样的错误是真的难以理解。。。

第三题

         var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//zhangsan
            }
        }
        obj.func();
复制代码

这题就是正常的题目了,不懂得话自己看第零题,如果代码这样改

         var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//window
            }
        }
        let func=obj.func;
        func();
        
复制代码

那么结果就应该是window了,同第零题解释。

第四题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//zhangsan
            }
        }
        let f=obj.func;
        f.apply(obj);
复制代码

这题就要讲apply了,可以用来改变this的指向,这里原来调用者本来是window但是由于使用了apply并传入调用者obj对象,所以this指向obj。

第五题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//zhangsan
            }
        }
        let f=obj.func;
        f.call(obj);
复制代码

没错,这题的要讲的就是call了,它也是用来改变this的指向,那么问题来了,有两个改变this的api我该用哪个呢?这就涉及到它们的1第二个参数了,由于在调用函数时候,有些函数是需要传入参数的(我这里的函数都是无参函数,所以看起来没区别),当要传参数的时候,二者的区别就出来了。看下面的例子

    var name1 = "window"
    let obj = {
        name1: "zhangsan",
        func: function(age, job) {
            console.log(`${this.name1}是个${age}岁的${job}`);
        }
    }
    let f = obj.func;
    f.call(obj, 18, "切图仔");
复制代码
    var name1 = "window"
    let obj = {
        name1: "zhangsan",
        func: function(age, job) {
            console.log(`${this.name1}是个${age}岁的${job}`);
        }
    }
    let f = obj.func;
    f.apply(obj, [18, "切图仔"]);
复制代码

看到这里相信你已经看出区别了,apply传参的时候传的是按数组传参,call传参的时候是按参数一个一个传。

第六题

        var name1="window"
        let obj={
            name1:"zhangsan",
            func:function(){
                console.log(this.name1);//都没执行。。。。。
            }
        }
        let f=obj.func;
        f.bind(obj);
复制代码

相信你已经知道答案了,没错又忘记bind不会直接调用,而是返回一个函数了吧,和上面两个相似,bind也是用来改变this的指向,但是此时函数不会立即指向,而是返回一个已改变this指向的函数,你需要手动调用一下,至于传递参数它也是一个参数一个参数的传。

第七题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);//name
                return s;
            }
        };
        let f = obj.func;
        let func=f();
        func();
复制代码

终于ES6中的箭头函数登场了,开始背:箭头函数没有自己的this,箭头函数中的this指向的是定义时的this,而不是执行时的this。-_-可是好像还是和我要的答案不一样,那就是理解错误了?还有的博客说,箭头函数在定义的时候this就确定了。???更加的迷糊了什么鬼。其实箭头函数没有自己的this,其this来源于其定义的时候的执行上下文的this,所以不是一定义就确定,而是要看最近的外层函数的this是什么,箭头的函数就是什么!!!很显然外层函数执行的时候的this是可以改变的,所以并不是说箭头函数在定义的时候this的指向就确定了,这是关键的地方,那么本题也就很好解释了,obj.func赋值给了全局的f后直接调用了,调用的对象就是全局的window,那么箭头函数的this就是window自然输出了全局的name1。让我们在看下一题进行对比。

第八题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);//zhangsan
                return s;
            }
        };
        let f = obj.func();
        f();
复制代码

借助上一题的解释,这一题的答案也是显而易见了,箭头函数的外层函数的执行调用者是obj,所以其this指向就是obj对象,那么自然箭头函数的this取决于外层函数的this,所以输出zhansan。

第九题

        var name1 = 'name';
        var obj = {
            name1: 'zhansan',
            func: function () {
                let s = () => console.log(this.name1);//zhansan
                return s;
            }
        };
        let f = obj.func();
        let B={
               name:"lisi"
        }
        f.call(B);
复制代码

如果你有认真的做前面的两道题,相信你这题也是可以对的,没错,由于箭头函数的外层函数的调用对象是obj,所以箭头函数的this就确定了,就是指向obj,即使你后来用改变this指向的call,apply,bing等都是步骤效的,要想改变this的指向就要改变func的调用者! 看到这里你是不是对this已经信心满满了呢?来看最后一题

第十题

    var length = 10;
    let fn = () => {
        console.log(this.length);//10 10
    }
    var obj = {
        length: 5,
        method: function(fn) {
            fn();
            arguments[0]();
        },
    };
    obj.method(fn, 1);
复制代码

ee看到length又看到arguments就知道这道题不简单,但是仔细想想this在定义的时候,this就由其定义的外层函数的指向调用者所决定了,这里很明显fn定义在全局,那它外层的指向上下文改不了只能是object,所以答案也就出来了就是:只要调用到fn函数,输出的都是全局的length:10,arguments只是一个幌子。。。。。

总结:

1.全局定义的函数,如果直接调用,this的指向就是window。 2.对象中的方法(普通方法),其this的指向由其调用者决定,谁调用我就指向谁,注意什么是调用!!!!(obj.fn只是获取函数,obj.fn()才是执行调用); 3.普通的函数,可以通过apply,call,bind注意三者的区别,apply传参要将参数放在数组中,bind和call要一个一个传,且bind不会执行改函数,还要手动调用一下。 4.箭头函数没有自己的this,其this的指向由定义时候的最近外层函数的this所决定,所以要改变其this的指向,应该改变它最近外层的函数执行对象! 5.还有就是要注意一些特殊的变量名,这里水太深了。 6.还有对象中的this,严格编译下的。。。。下次一定

刚开始写博客,有不对的地方欢迎指出呀,也欢迎大家在讨论区,说说自己在学习工作买菜中遇到的和this相关的坑呀

猜你喜欢

转载自juejin.im/post/7031441572952539143
今日推荐