var names = 'window person';
const person = {
names: 'object person',
sayNamePerson() {
console.log(this.names);
},
sayArrowPerson: () => {
console.log(this.names);
},
};
const sayNamePerson = person.sayNamePerson;
sayNamePerson(); // ===> window person
person.sayNamePerson(); // ===> object person
person.sayArrowPerson(); // ===> window person
sayNamePerson.call(window); // ===> window person
person.sayArrowPerson.call(person); // ===> window person
在这个JavaScript代码示例中,我们有一个字符串names
和一个对象person
。person
对象有两个方法:sayNamePerson
和sayArrowPerson
。这两个方法的主要区别在于它们如何绑定this
关键字。
1.sayNamePerson()
方法(非箭头函数):
- 当
sayNamePerson
方法被赋值给sayNamePerson
变量并以独立函数调用时(sayNamePerson();
),this
在默认情况下指向全局对象(在浏览器中是window
)。但是,在严格模式('use strict';
)下,this
会是undefined
。由于代码中没有启用严格模式,这里this
指向window
。然而,window
上没有names
属性(除非在其他地方定义了),所以这里实际上会打印undefined
,但根据问题描述,我们假设这里的意图是解释this
的指向,因此注释// 1
处预期输出应该是基于window
的上下文(如果有window.names
则为'window person'
,否则为undefined
)。 - 当通过对象
person
调用sayNamePerson()
方法时(person.sayNamePerson();
),this
指向调用它的对象person
,因此会打印person
对象中的names
属性值:'object person'
。
2.sayArrowPerson
方法(箭头函数):
- 箭头函数不绑定自己的
this
,它会捕获其所在上下文的this
值作为自己的this
值。在这个例子中,sayArrowPerson
方法是在person
对象的上下文中定义的,但由于箭头函数不绑定自己的this
,实际上它在这里没有捕获到person
作为this
的值(因为箭头函数在定义时还没有明确的调用上下文)。在对象字面量中定义箭头函数时,this
通常是undefined
(在严格模式下会报错,非严格模式下则取决于具体的JavaScript引擎实现,可能默认指向全局对象如window
)。然而,这里的关键是箭头函数的this
是在定义时被决定的,而不是在调用时。因此,不论是通过person.sayArrowPerson();
还是其他方式调用,this
都不会指向person
对象。 - 当尝试通过
person.sayArrowPerson();
调用时,由于this
在箭头函数定义时并未绑定到person
,这里的this
值取决于箭头函数定义时的上下文(在这个例子中并不明确,但通常不会指向person
)。然而,如果this
在箭头函数定义时由于某种原因(如非严格模式下的全局作用域)指向了window
,则输出将是window
的names
属性值(如果有的话)。但基于问题的上下文,这里主要关注this
的绑定行为,而不是具体的输出值。 - 使用
.call()
方法改变this
的指向对于箭头函数是无效的,因为箭头函数不绑定自己的this
。
3.
使用.call()
方法:
sayNamePerson.call(window);
:这里显式地将this
绑定到window
对象,并调用sayNamePerson
方法。如果window
上有names
属性,将打印该属性的值;否则,打印undefined
。person.sayArrowPerson.call(person);
:尝试使用.call()
方法将this
绑定到person
对象对于箭头函数是无效的。箭头函数会忽略.call()
、.apply()
或.bind()
方法传递的this
值。因此,这里的this
仍然指向箭头函数定义时的上下文(在这个例子中不明确)。
总结:
sayNamePerson()
(非箭头函数)的this
在调用时根据调用方式确定。sayArrowPerson
(箭头函数)的this
在定义时确定,且不能通过.call()
、.apply()
或.bind()
改变。
注意:实际输出可能会因JavaScript引擎的实现和是否处于严格模式而有所不同。