JavaScript的this关键字的小结¶
在Java等面向对象语言里,this的功能是比较清晰的,它一定是指向当前对象(正在被调用的方法所属的对象)。
而在JS里,情况会更复杂些。
JS this的几种不同指向¶
- 在对象的方法里,this指向该对象。
- 在函数里:
- 严格模式下,this的值为undefined。
- 非严格模式下,this指向全局对象。
- 在脚本里(不在方法或者函数)里,this指向全局对象。
call()
、apply()
、bind()
可以让this指向任意对象。- ES6箭头函数里的this和上面的几种this有本质的不同,它实际上和箭头函数上下文里的this是同一个this。听起来有点费解,具体请看最后面的章节。
注意:
- 全局对象(global object),在浏览器环境下是指
window
对象 - 在JS里,函数和方法是不同的概念!具体见下个章节。
方法vs函数¶
先看一个方法的例子:
const user = {
username: "jack",
hello : function() {
console.log('hello ' + this.username)
}
};
user.hello();
输出:
hello jack
当执行user.hello()
方法时,方法内部的this
指向的实际是user
对象,因此输出的this.username
等同于user.username
。
接着上面的代码,我们再补充一个函数例子:
var hello = user.hello;
hello();
输出:
hello undefined
上面的代码里,我们将方法user.hello
赋值给hello
变量,然后再执行hello()
,结果,输出变了,this.username
不再是jack
,而是undefined
。
之所以出现这个怪相,是因为,hello
变量是一个函数,而不是方法,只有对象名.方法名()
的形式才是方法调用,其他情况是函数调用!根据我们前面对this的解释,在函数中,this指向全局对象window(暂不考虑strict模式),那么函数内部的this.username
就等同于window.username
,而window
没有username属性,即,window.username
的值是undefined
。
call()
、apply()
、bind()
的比较¶
三者都可以指定this的值。我们接下来通过代码示例来了解它们。
首先,准备好这两个对象,jack对象拥有一个hello方法,tom对象没有方法。我们将分别通过call()
、apply()
、bind()
来让jack.hello()
方法中的this
指向tom
对象。
const jack = {
username: "jack",
hello : function(times) {
for(let i = 0; i < times; i++) {
console.log('hello ' + this.username);
}
}
};
const tom = {username: "tom"};
借助call()
:
jack.hello.call(tom, 2);
借助apply()
:
jack.hello.apply(tom, [2]);
借助bind()
:
var hello = jack.hello.bind(tom);
hello(2);
上述三段代码的输出都是:
hello tom
hello tom
上述3个代码段,都实现了我们想要的效果,hello方法得到正常运行,而且输出的this.username
实际确实是tom的username,而不是jack的username。
注意:
- call和apply的功能类似,都是修改函数的this并执行函数。区别在于,前者的函数参数是直接传入的,后者的函数参数是打包成一个数组传入的。
- bind不会立即执行函数,而是返回一个新函数。
ES6箭头函数的this¶
ES6箭头函数里的this和上面的几种this有本质的不同,它实际上和箭头函数上下文里的this是同一个this。
这个说法有点拗口,我们直接看代码:
const jack = {
username: "jack",
hello: () => console.log(this.username)
};
jack.hello();
这段代码的输出是undefined
,而不是"jack"
。看上去很不符合直觉,因为,假如hello
不是箭头函数,而是普通function的时候,this
应当会绑定到(指向)jack
对象,那么jack.hello()
输出的this.username
就应该是"jack"
。
实际上,箭头函数() => console.log(this.username)
内部的所谓this
实际上和箭头函数外部的this
是同一个东西!箭头函数内部只是访问了一下上下文里的this
。示例代码里,箭头函数的上下文就是定义jack
变量、执行jack.hello();
的这段代码,对于这段代码而言,this
自然指向window
。于是,箭头函数里访问this.username
等同于访问window.username
!
本文为kyleblog.cn原创,转载请注明出处:https://www.kyleblog.cn/posts/js_this
发布日期:2022-08-16 联系作者