理解js中this的指向
你越是认真生活,你的生活就会越美好
——弗兰克·劳埃德·莱特
《人生果实》经典语录
this的指向在函数定义的时候确定不了,只有函数执行的时候才能确定this指向谁,实际上this的最终指向的是调用它的对象
规则
- 如果一个函数中有this,但是它
没有被上一级的对象所调用
,那么this指向
的就是window
,严格模式指向undefined - 如果一个函数中有this,这个函数
有被上一级的对象所调用
,那么this指向
的就是上一级的对象
。 - 如果一个函数中有this,这个
函数中包含多个对象
,尽管这个函数是被最外层的对象
所调用,this指向的也只是它上一级的对象
this永远指向的是最后调用它的对象
,也就是看它执行的时候被谁调用
,
下面例子4
中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行
,所以最终指向的是window
当this碰到return时
- 如果
返回值是一个对象
,那么this指向返回的对象
,如果返回值不是对象
那么this还是指向函数的实例
。 - 虽然
null
也是对象,但是在这里this还是指向那个函数的实例
,因为null比较特殊。 - .在严格版中的默认的this不再是window,而是undefined。
例子1:
function a(){
const name = "泓";
console.log(this); // Window
console.log(this.name); // undefined 相当于window.user 不会打印出"泓"
}
a();
按照我们上面说的this最终指向的是调用它的对象
,
这里的函数a
实际是被Window对象
所调用的,等同于下面的代码
function a(){
const name = "泓";
console.log(this); // Window
console.log(this.name); // 相当于window.name 不会打印出"泓"
}
window.a();
例子2:
const obj = {
name: "泓",
fn() {
console.log(this.name) // 泓 这里的this指向obj对象
}
}
obj.fn() // '泓' fn()被obj对象调用
这里的this指向的是对象obj,因为调用这个fn是通过obj.fn()执行的
,
这里再强调一次,this的指向在函数创建的时候还没法确定,在调用的时候才能确定,也就是谁调用的就指向谁
接下来的例子会更复杂些
例子3:
var obj = {
name:"泓",
fn:function(){
console.log(this.name); // 泓 this指向obj对象
}
}
window.obj.fn(); // 泓
这段代码和上面的那段代码几乎一样,但是这里的this为什么不是指向window,如果按照上面的规则,this的指向在函数创建的时候还没法确定,在调用的时候才能确定,也就是谁调用的就指向谁
,最终this指向的是调用它的对象,window是js中的全局对象
,我们通过var
创建的变量实际上是给window添加属性,所以这里可以用window.obj调用obj对象
这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码。
var obj = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12 这里this指向obj对象里的b对象
}
}
}
obj.b.fn(); // 12
this的指向在函数创建的时候还没法确定,在调用的时候才能确定,也就是谁调用的就指向谁
这里同样也是对象obj调用,但是访问Obj.b
时,并没有执行fn
方法
访问obj.b.fn()
时才执行了fn
方法,所以这里this
指向b
对象
-
情况1:如果一个函数中有
this
,但是它没有被上一级的对象所调用
,那么this指向
的就是window
,这里需要说明的是在js的严格版中this指向的不是window,这里不探讨严格版
的问题 -
情况2:如果一个函数中有
this
,这个函数有被上一级的对象所调用
,那么this指向的就是上一级的对象。 -
情况3:如果一个函数中有this,这个
函数中包含多个对象
,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
上面的例子3可以证明,接下来我们继续看几个例子。
var obj = {
a:10,
b:{
fn:function(){
console.log(this.a); //undefined this指向obj对象里的b对象
}
}
}
obj.b.fn(); // undefined
尽管对象b中没有属性a,这个this指向的也是对象b
,因为this只会指向它的上一级对象
,不管这个对象中有没有this要的东西。
还有一种比较特殊
的情况,例子4:
var obj = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a);
console.log(this);
}
}
}
var obj1 = obj.b.fn; // 这里只是赋值
obj1();
// 这里obj1相当于
obj1 = function() {
console.log(this.a);
console.log(this);
}
obj1() // 这时obj对象里的this指向window
this永远指向的是最后调用它的对象
,也就是看它执行的时候被谁调用
,
例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行
所以最终指向的是window,这和例子3不一样,例子3直接执行了fn。
构造函数版this:
function Fn(){
this.name = "泓";
}
var a = new Fn();
console.log(a.name); // 泓
new关键字
new关键字会创建一个空的对象
,然后会自动调用一个方法,将this指向这个空对象
,这样的话函数内部的this就会被这个空的对象替代。
我们还可以自行改变this的指向,关于自行改变this的指向请看JavaScript中call,apply,bind方法的总结这篇文章,详细的说明了我们如何手动更改this的指向。
当this碰到return时
- 如果
返回值是一个对象
,那么this指向
的就是那个返回的对象
,如果返回值不是一个对象
那么this
还是指向函数的实例
。 - 还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
- .在严格版中的默认的this不再是window,而是undefined。
return返回值为对象,this指向返回的对象
function Fn()
{
this.name = '泓';
return function(){};
}
var a = new Fn;
console.log(a.name); // undefined
return返回值不是对象,this还是指向实例
function Fn()
{
this.name = '泓';
return 1;
}
var a = new Fn;
console.log(a.name); // 泓
return返回值不是对象,this还是指向实例
function Fn()
{
this.name = '泓';
return undefined;
}
var a = new Fn;
console.log(a.name); // 泓
return返回值是null,this还是指向实例
function Fn()
{
this.name = '泓';
return null;
}
var a = new Fn;
console.log(a.name); // 泓
改变this指向-call,apply,bind
- call、apply、bind方法第一个参数指定this指向的对象,再往后的参数作为调用方法的参数
- apply方法第二个参数是数组
- 如果call和apply的第一个参数写的是null,那么this指向的是window对象
- bind方法跟call、apply有点不同,返回的是修改后的新函数
call()
var a = {
name: '泓',
fn: function() {
console.log(this.name)
}
}
var b = a.fn
b() // undefined this指向window
b.call(a) // 泓 this原本指向window call()第一个参数将this指向变成了对象a
call方法除了第一个参数以外还可以添加多个参数,如下
var a = {
name: '泓',
fn: function(a, b) {
console.log(this.name)
a && b &&
console.log(a + b)
}
}
var b = a.fn
b() // undefined this指向window
b.call(a, 2, 5) // 泓 7 this指向了a对象,同时2,5作为b函数的参数传入
apply()
apply()方法与call()方法类似,不同点apply第二个参数必须是一个数组
var a = {
name: '泓',
fn: function(a, b) {
console.log(this.name)
a && b &&
console.log(a + b)
}
}
var b = a.fn
b() // undefined this指向window
b.apply(a, [2, 5]) // 泓 7 this指向了a对象,同时2,5作为b函数的参数传入
bind()
var a = {
name: '泓',
fn: function(a, b, c) {
console.log(this.name)
a && b && c &&
console.log(a,b,c)
}
}
var b = a.fn
b() // undefined this指向window
b.bind(a, 1) // 返回的是一个函数,this指向a对象,函数第一个的参数为1
// 调用
var c = b.bind(a, 1)
c(2,3) // 泓 1 2 3
推荐阅读
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强