javascript中的this(主要说箭头函数的this)

基本原则:

1,普通函数的 this 是在调用时决定的,它的值取决于函数的调用方式。
当一个普通函数作为对象的方法被调用时,this 将引用该对象。
当一个普通函数独立调用时,this 的值将取决于函数执行环境。
2,构造函数中:当函数作为构造函数使用时,"this"指向新创建的对象。
3,箭头函数,没有自己的 this 绑定,而是继承外部作用域的 this 值。而不是由函数调用方式决定的。跟写代码时的位置关系比较大。
 


详解:

1,全局环境下:在全局作用域中,函数被直接调用时,"this"指向全局对象。例如:

console.log(this); // 指向全局对象(如浏览器中的"window"对象)

2,对象方法中:当函数作为对象的方法被调用时,"this"指向该对象。例如

const obj = {
  name: "Alice",
  sayHello: function() {
    console.log("Hello, " + this.name);
  }
};

obj.sayHello(); // 输出:Hello, Alice

3,构造函数中:当函数作为构造函数使用时,"this"指向新创建的对象。例如:

function Person(name) {
  this.name = name;
}

const person = new Person("Bob");
console.log(person.name); // 输出:Bob

 4,使用"call"或"apply"方法:可以使用"call"或"apply"方法显式地设置函数的上下文,并将"this"指向指定的对象。例如

function sayHello() {
  console.log("Hello, " + this.name);
}

const obj = { name: "Charlie" };
sayHello.call(obj); // 输出:Hello, Charlie

 5,箭头函数不同于普通函数,它没有自己的 this 绑定,而是继承外部作用域的 this 值。而不是由函数调用方式决定的。跟写代码时的位置关系比较大。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        let this_general = null;
        let this_arrow = null;
        let obj = {
            name: 'Alice',
            greet: function () {
                this_general = this; //由于greet函数是以对象的方法被调用的即obj.greet(),所以this指向obj对象
                setTimeout(() => {
                    //箭头函数中this继承外部作用域中的this,外部作用域是greet函数,也就是继承greet函数中的this,
                    //greet函数是以对象的方法被调用的,所以greet函数中的this指向obj对象,所以箭头函数中的this也指向obj对象。
                    this_arrow = this;   
                }, 1000);
            }
        };


        obj.greet();
        setTimeout(() => {
            console.log(this_general); //输出对象obj
            console.log(this_arrow);   //输出对象obj
            console.log(this_general === this_arrow);  //true
        }, 2000);

    </script>

</body>

</html>


6,重点难点,搞明白下边5种情况,看注释,主要是搞明白外层作用域!

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <script src="./vue.js"></script> -->
</head>

<body>
    <script>
        let a = 1;
        {
            let a = 2;
            let b = {
                a: 3,
                c: {
                    a: 4,
                    d: function () {   //第1种情况
                        //这里输出2。而不是1、3、4,可见,这里的作用域是和“let a = 2;”相同的。也就是说对象b和c并不是作用域。
                        console.log('函数f输出的a:', a);
                        //由于此函数不是箭头函数,当函数作为对象中的方法被调用时this指向该对象,所以这里的this指向对象{a: 4, d: ƒ, f: ƒ},即对象b.c。
                        console.log('函数d输出的this:', this);
                    },
                    f: () => {   //第2种情况
                        //这里输出2。而不是1、3、4,可见,这里的作用域是和“let a = 2;”相同的。也就是说对象b和c并不是作用域。
                        console.log('函数f输出的a:', a);
                        //在箭头函数中,this 的值是由外层作用域决定的(写代码位置的外层作用域),而不是由函数调用方式决定的。
                        //那外层作用域是哪里呢?我们把这里的this改成a,输出一下就知道作用域了,改成a后输出是2,可见这里的作用域是和“let a = 2;”相同的。也就是说对象b和c并不是作用域。
                        //所以这里的this,就继承了“let a = 2;”那里的this,由于那里的this指向的是Window对象,所以这个箭头函数的this也指向Window对象
                        console.log('函数f输出的this:', this);
                    },
                    //第3情况。这里的this指向Window对象。因为b.c.g不是对象中的方法(因为它根本不是方法),所以这里的this 的值是由外层作用域决定的(写代码位置的外层作用域)。
                    //那外层作用域是哪里呢?我们把这里的this改成a,输出一下就知道作用域了,改成a后输出是2,可见这里的作用域是和“let a = 2;”相同的。也就是说对象b和c并不是作用域。
                    //所以这里的this,就继承了“let a = 2;”那里的this,由于那里的this指向的是Window对象,所以这个箭头函数的this也指向Window对象
                    g: this,
                },

            }
            b.c.d(); //见第1种情况的注释 this指向对象{a: 4, d: ƒ, f: ƒ},即对象b.c
            b.c.f(); //见第2种情况的注释  this指向Window对象
            console.log(b.c.g);//见第3种情况的注释 this指向Window对象
            console.log('花括号作用域内的this:', this);  //第4种情况,输出Window对象。由于{}花括号只是一个作用域,它并没有自己的this,所以向外找到了全局的Window对象
        }

        {
            let this_general = null;
            let this_arrow = null;
            let obj = {
                name: 'Alice',
                greet: function () {
                    this_general = this; //由于greet函数是以对象的方法被调用的即obj.greet(),所以this指向obj对象
                    setTimeout(() => {
                        //第5种情况
                        //箭头函数中this继承外部作用域中的this,外部作用域是greet函数,也就是继承greet函数中的this,
                        //greet函数是以对象的方法被调用的,所以greet函数中的this指向obj对象,所以箭头函数中的this也指向obj对象。
                        this_arrow = this;
                    }, 1000);
                }
            };
            obj.greet();
            setTimeout(() => {
                console.log(this_general); //输出对象obj
                console.log(this_arrow);   //输出对象obj
                console.log(this_general === this_arrow);  //true
            }, 2000);
        }
    </script>

</body>

</html>

上边5种情况的输出

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值