重学JS | this的指向问题

381 阅读2分钟

这是我参与更文挑战的第7天,活动详情查看:更文挑战

[重学JavaScript系列文章连载中...]

this并不是JavaScript特有的特性,在c++、java等面向对象的语言中也存在这个关键字。他们中的this很好理解,指向的是当前类的实例对象。那在JavaScript中呢,我们先看两个例子:

function Person(name){
	this.name = name
}

// 1. 当作构造函数调用
let p = new Person('程序员')
// 输出:程序员
// 可以看到实例可以访问到绑定在this上的属性,this指向p实例
// 因为new操作符可以改变this指向,详情可以看之前的文章:深入理解Object
console.log(p.name) 

// 2. 普通函数调用
function Man(name){
	this.name = name
}
Man('程序猿')
console.log(window.name) // 程序猿,this指向了window对象,Man函数没有所属对象

从例子可以看出,随着函数执行,就会产生一个this值,这个this值存储着调用该函数的对象的值。因此可以推断,this指向的永远是函数的调用者。

举几个this指向的场景:

  1. 函数没有所属对象而直接调用时,this指向的是全局对象
var val = 1
var obj = {
	val:2,
  method:function(){
  	let foo = function(){
    	console.log(this.val)
    }
    foo() // foo函数的执行没有绑定对象,所以this指向window
  }
}
obj.method()  // 1
  1. this指向所属对象
var val = 1
var obj = {
	val:2,
  method:function(){
  	console.log(this.val)
  }
}
obj.method() // 2,this指向函数所属对象obj
  1. this指向call/apply/bind函数调用后重新绑定的对象
var val = 1
var obj = {
	val:2
}
var method = function(){
	console.log(this.val)
}
method() // 1 方法没有绑定对象,执行window
method.call(obj)  // 2 ,call将函数调用的主体改为到obj
method.apply(obj) // 2 ,apply将函数指向的主体改为obj

var newM = method.bind(obj) // bind将函数指向的主体改为obj
newM() // 2

再看个经典的例子:

function f(k){
	this.m = k
  return this
}

var m = f(1)
var n = f(2)
console.log(m.m) // 2.m  undefind
console.log(n.m) // 2  window.n.m = window.m = 2

f()函数的调用没有所属对象,所以this指向window

当执行f(1)this.m = window.m = 1,返回this,即返回window,所以此时window.m = window

当执行f(2),this同样指向windowthis.m = window.m = 2,通过return语句将window赋值给n,此时window.n = window

所以m.m = 2.m ,输出undefinedn.m = (window.n).m = window.m = 2

至此我们大体学习了this的相关指向知识。

里面关于new操作符改变this指向的问题,可以查看文章:

重学 JS | 深入理解 Object,必会知识点汇总