2

前言

先做一个小测试,如果全部答对了,恭喜你不用往下看了。

第一题

<script>
    var str = 'zhangsan';

    function demo() {
        var str = 'lisi';
        alert(this.str);
    }
    window.demo(); // ??

    var obj = {
        str: "wangwu",
        say: function() {
            alert(this.str);
        }
    }
    obj.say(); // ??

    var fun = obj.say;
    window.fun(); // ??
</script>

第二题

<script>
    var username = 'zhangsan';

    (function() {
        var username = 'lisi';
        alert(this.username); // ??
    })()

    function demo() {
        var username = 'wangwu';

        function test() {
            alert(this.username);
        }

        test(); // ??
    }
    demo();
</script>

第三题

<script>
    function Person() {
        this.username = 'zhangsan';
        this.say = function() {
            alert('我叫' + this.username);
        }
    }

    var p = new Person();
    p.say(); // ??

    var p1 = new Person();
    p1.say(); // ??
</script>

第四题

<script>
    var username = 'zhangsan';

    function demo() {
        alert(this.username)
    }

    var obj1 = {
        username: "lisi"
    };
    var obj2 = {
        username: "wangwu"
    };

    demo(); // ??
    demo(obj1); // ??
    demo(obj2); // ??
    demo.call(obj1); // ??    
    demo.apply(obj2); // ??
</script>

答案

第一题:zhangsan wangwu zhangsan
第二题:zhangsan zhangsan
第三题:我叫zhangsan 我叫zhangsan
第四题:zhangsan zhangsan zhangsan lisi wangwu
(往下看,下面有详细解析哦)

this

  1. 指向调用函数的对象

  2. 无对象调用函数/匿名函数自调用(this指向window)

  3. 通过new产生的对象

  4. apply/call调用

一、指向调用函数的对象

<script>
    // this:指向调用函数的对象
    var str = 'zhangsan';

    function demo() {
        var str = 'lisi';

        //this->window
        console.log(this);
        alert(this.str);
    }
    window.demo(); // zhangsan

    var obj = {
        str: "wangwu",
        say: function() {
            // this->obj
            alert(this.str);
        }
    }
    obj.say(); // wangwu

    var fun = obj.say;
    window.fun(); // zhangsan
</script>
  • 全局函数(demo)属于window对象的方法,window调用demo所以this就指向了window

  • obj调用say方法,this就指向了obj

  • fun()是全局函数,而声明的fun接收的是obj里面单纯的一个函数,并没有调用(obj.say()才是调用了函数),此时的fun就是一个函数(function(){alert(this.str);}),那么当fun()调用函数的时候,this指向的就是window

  • 是谁调用的函数,那么this就指向谁

二、无对象调用函数/匿名函数自调用->this指向window

<script>
    // 2.匿名函数自执行|匿名函数|无主函数 this->window
    var username = 'zhangsan';

    // 匿名函数自执行 this->window
    (function() {
        var username = 'lisi';
        console.log(this); // window
        alert(this.username); // zhangsan
    })()

    function demo() {
        var username = 'wangwu';

        // 无主函数 this->window
        function test() {
            // this->window
            alert(this.username);
        }

        test(); // zhangsan
    }
    demo();
</script>
  • 因为匿名函数没有名字,所以就挂给window了

  • test(),谁调用test那么就指向谁。当然实验过,它不是window调用的,也不是demo调用的,没有人管它,那么它就指向window。它就相当于一个没有主人调用它,无主函数。

三、通过new产生的对象

<script>
    // 3.通过new的对象:this指向产生的对象
    // 函数
    function Person() {
        // 属性
        this.username = 'zhangsan';
        // 方法
        this.say = function() {
            // this->p
            console.log(this); // Person对象
            alert('我叫' + this.username);
        }
    }

    // 实例化出一个对象:p就具有了username属性和say方法
    var p = new Person();
    console.log(p); // Person对象
    console.log(p.username); // zhangsan
    p.say(); // 我叫zhangsan

    // this->p1
    var p1 = new Person();
    p1.say(); // Person对象 我叫zhangsan
</script>
  • 当我们的函数Person里面运用了this去写属性和方法这种格式,那么就要通过new来让属性和方法变得有价值,通过new去运用函数里面的属性和方法

四、apply/call调用

首先我们来了解下apply()/call()是个什么东西呢?

apply()/call():最终是调用function,只不过内部的this指向了thisObj

function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
function.apply([thisObj[,argArray]])

注意:
1. 调用function函数,但是函数内的this指向thisObj(更改对象内部指针)
2. 如果thisObj没有传参,则默认为全局对象
3. call()/apply()联系与区别
    联系:功能一样,第一个参数都是thisObj
    区别:传递的参数如果比较多
        call()的实参就是一一列出
        apply()的实参是全部放置在第二个数组参数中
        
        

一个理解apply()/call()的实例:

<script>
    // apply()/call()
    function demo() {
        console.log(123);
    }

    // 调用函数的时候,demo.call()/demo.apply()最终调用的还是demo()
    demo(); // 123
    demo.call(); //123
    demo.apply(); // 123
</script>

<script>
    // call()/apply()的区别:
    // call()参数单独再call中罗列
    // apply()的参数通过数组表示
    function demo(m, n, a, b) {
        alert(m + n + a + b);
    }
    demo(1, 5, 3, 4); // 13
    demo.call(null, 1, 5, 3, 4); // 13
    demo.apply(null, [1, 5, 3, 4]); // 13
</script>

this的第四个用法实例

<script>
    // this的第四个用法:call(obj)/apply(obj):强制性的将this指向了obj
    var username = 'zhangsan';

    function demo() {
        alert(this.username)
    }

    var obj1 = {
        username: "lisi"
    };
    var obj2 = {
        username: "wangwu"
    };

    // call()/apply():打劫式的改变了this的指向
    demo(); // zhangsan
    demo(obj1); //zhangsan
    demo(obj2); //zhangsan
    demo.call(obj1); // lisi    
    demo.apply(obj2); // wangwu
</script>
  • 如果直接调用demo里面写的不管是obj1还是obj2,那么demo还是属于window调用的。

  • 不管你用call还是apply最终调用的都是demo函数,但它们会强制的this指向了obj1/obj2,强制的指向了它们的第一个参数对象。


lanfang
375 声望9 粉丝

我是一个程序媛