首先我们来声明一个js对象person:
var person = { talk() { console.log("I am talking..."); }};复制代码
然后调用person对象的talk方法:
person.talk();复制代码
结果如下:
没有任何问题,然后我们将person对象的talk方法赋值给一个全局变量talk,并调用这个全局的talk方法:
var talk = person.talk;talk();复制代码
结果如下:
现在我们来给person对象新增属性name和方法sayName,修改之后的person对象如下:
var person = { name: 'xiaoming', talk() { console.log("I am talking..."); }, sayName() { console.log("My name is " + this.name); }}复制代码
调用person对象的sayName方法:
person.sayName();复制代码
结果如下:
没有任何问题,输出的name是person对象的name属性,然后我们将person对象的sayName方法赋值给一个全局变sayName,并调用这个全局的sayName方法:
var sayName = person.sayName;sayName();复制代码
结果如下:
undefined
,这是由于我们调用sayName方法时,是在全局作用域下调用的该方法,对比一下: //调用person对象的sayName方法:person.sayName();调用全局的sayName函数,浏览器环境下相当于调用:window.sayName();复制代码
而此时顶级对象window下并没有name属性,所以输出undefined
。
这里多提几句,之前关于this的分析全是基于浏览器运行环境下的,如果在node下声明函数,this指向的是global对象,而在该node模块中声明的全局变量属于该模块,不属于global对象,如果想要将全局变量绑定到global,那么需要在不使用var或者let等关键词,就可以挂载到global上了。
我们再拓展一下,如果在定时器中使用this是指向什么作用域呢?、 在person对象中新增一个方法sayNameLater,修改之后的person对象如下:
var person = { name: 'xiaoming', talk() { console.log("I am talking..."); }, sayName() { console.log("My name is " + this.name); }, sayNameLater() { setTimeout(function() { console.log("My name is " + this.name); },1000); }}复制代码
调用person对象的sayNameLater方法:
person.sayNameLater();复制代码
结果如下:
undefined
,这是由于我们在使用定时器时,函数中的this会指向window对象(浏览器环境下),如果我们此时声明全局变量name并赋值: var name = "xiaohong";复制代码
再调用person对象的sayNameLater方法:
person.sayNameLater();复制代码
结果如下:
使用定时器时,函数中的this会指向window对象,即使我们使用对象方法而不是函数,this依然会指向window对象。现在person对象不变,全局变量name不变,在定时器中调用person对象的sayName方法:
var name = "xiaohong";var person = { name: 'xiaoming', talk() { console.log("I am talking..."); }, sayName() { console.log("My name is " + this.name); }, sayNameLater() { setTimeout(function() { console.log("My name is " + this.name); },1000); }}setTimeout(person.sayName, 1000);复制代码
结果如下: