(共566篇)
全部分类

神奇的this
[ JS基础 ] 

神奇的 this

JS 中有一个类似《X 战警》中变形女角色的存在this。它的值不是固定的,随时都在发生变化。

本文的所有案例都是在浏览器环境下执行的

函数外的 this

在函数外使用 this 时,this指向全局变量window,也就是说var name = 'lilywindow.name = 'lily'以及this.name = 'lily的结果其实是相同的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<script>
    console.log("this === window", this === window);
    var name = "lily";
    console.log("name: ", name);

    window.name = "zhangsan";
    console.log("name: ", name);

    this.name = "lisi";
    console.log("name: ", name);
</script>

代码案例

函数内的 this

函数内的 this,要分为两种情况

直接调用函数

直接调用函数时函数内的 this 指向 window 对象

1
2
3
4
5
6
<script>
    function add() {
        console.log("this == window", this == window);
    }
    add();
</script>

代码案例

被其他对象调用

被其他对象调用时,函数内的this和调用函数的对象有关:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<script>
    var p1 = {
        name: "zhangsan",
        run: function() {
            console.log("this.name:", this.name);
            console.log("this == p1", this === p1);
        },
    };
    p1.run();
</script>

代码案例

再看一个案例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script>
    var p1 = {
        name: "zhangsan",
        run: function() {
            console.log("this.name:", this.name);
            console.log("this == p1", this === p1);
            console.log("this == p2", this === p2);
        },
    };
    var p2 = {
        name: "lisi",
        run: p1.run,
    };
    p2.run();
</script>

代码案例

在这个案例中,p1.run的值被重复赋值给p2.run属性。p2run()方法的实际调用者,所以run()方法中的this指向的是p2

再来看一个:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<script>
    var name = "zhangsan";
    var p1 = {
        name: "lisi",
        run: function(a) {
            console.log("this.name:", this.name);
        },
    };
    p1.run();

    var foo = p1.run;
    foo();
</script>

代码案例

上面这个案例中,第一次的run方法是被p1调用的,所以函数中的 this 指向了调用者p1;那么p1.name的值就是lisi;

第二次run的属性值被赋值给了一个单独的变量foofoo()实际上是直接调用了函数,它没有调用者,所以this指向了window对象。window.name的值是zhangsan

再来一个:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
    function foo() {
        console.log("this.a", this.a);
    }

    function active(fn) {
        fn(); // 没有调用者
    }

    var a = 20;
    var obj = {
        a: 10,
        getA: foo,
    };

    active(obj.getA);
</script>

代码案例

这个案例中foo函数被赋值给了obj.getA属性,又被作为参数传递给active函数,在active中调用的时候,实际上还是直接执行的,没有调用者,所以函数中的this还是指向了window,所以window.a的值是20

数组中的函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<script>
    function foo() {}
    var arr = [
        10,
        function() {
            console.log("this == window", this == window);
            console.log("this == arr", this == arr);
            console.log("this[0]=", this[0]);
        },
    ];
    arr[1]();
</script>

代码案例

上面案例中,数组中的函数执行的时候,实际上是被数组调用的,也就是说数组是函数的实际调用者,所以函数中的this指向了调用者arr本身。