在JavaScript中,函数内的this关键字的行为非常依赖于函数是如何被调用的。在user, user2, 和 user3的例子中,sayHi函数被定义了三种不同的方式,这导致this的行为也存在差异。

user对象

这里使用了一个名为sayHi的普通函数表达式:

let user = {
    name: "Tom",
    sayHi: function () {
        console.log('Hi, I am ' + this.name);
    }
}

在这个例子中,sayHi是一个普通的函数属性。当它作为方法(即通过对象引用调用时,例如user.sayHi())被调用时,this指的是调用它的对象,即user。

user2对象

这里使用了一个ES6中的方法简写:

let user2 = {
    name: "Jack",
    sayHi() {
        console.log('Hi, I am ' + this.name);
    }
}

user2例子中的sayHi定义和user的很相似,唯一的区别是它使用了ES6的简化语法来创建方法。这并不改变this的行为:作为user2对象的方法被调用时,this同样指向user2。

user3对象

这里使用了箭头函数:

let user3 = {
    name: "Ben",
    sayHi: () => {
        console.log('Hi, I am ' + this.name);
    }
}

user3.sayHi使用了一个箭头函数,箭头函数不绑定this,相反,它们捕获定义时上下文的this值。在全局代码中定义的箭头函数中的this指向全局对象,在浏览器中通常是window。因此,无论你何时何地调用user3.sayHi,它打印出来的this.name总会引用定义时捕获的this的name属性,而不是user3的name属性。如果user3.sayHi在全局范围内定义,如在浏览器中使用<script>直接定义,则this.name很可能是undefined。

关于setTimeout
当你直接传递方法给setTimeout,如setTimeout(user.sayHi, 1000),你传递的是函数本身,而不是函数的调用。结果是,当setTimeout执行这个函数时,它没有了对象上下文,因此this不再引用原始的对象,除非像user和user2示例中一样使用.bind()方法明确地绑定this。
总结下三者间的区别:
user和user2展示了在对象内部定义方法的两种方式,都可以使用sayHi作为方法调用,其中this指向调用的对象。
user3的箭头函数导致this在定义时就固定下来,对箭头函数使用bind是无效的,因为箭头函数不绑定this。
使用.bind()可以修正setTimeout调用中this的指向,确保当方法在将来某个时间点执行时,this指向正确的对象。

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required