到底谁是this?

153 阅读2分钟

this可能是每一个前端永远绕不开的东西,也是最让人难以琢磨的东西之一,到底谁是this? 其实JavaScript中的this跟它在哪?以及怎么用?有着比较密切的关系!

在函数中

x = 10;
function add(y) {
	return this.x + y
}
console.log(add(20))

这里很容易得出答案:30

是的,这个this指的就是window,因为调用add函数的就是window对象,而x也是window的属性,这很容易理解。

在对象的方法中

var obj = {
	x: 10,
    log: function() {
    	console.log(this.x);
    }
}
obj.log()

这里是怎么用它的呢?很显然,就是obj这个对象调用了它,那这个this 显然就是 obj咯!所以这里打印出了 10

这个例子可能很容易让人误以为this定义在obj的方法中,所以它总是指向obj

但是

var global = obj.log; 
global();

如果我们这样用呢?这里我们把log方法赋给了一个global变量;那这个时候this就是再指向obj了,而是window;因为global()就相当于window.global(),而window对象并没有x属性,所以这里会输出undefine

再来看一个例子

var obj = {
	x: 10,
    log: function() {
    	console.log(this.x)
    }
}
var target = {
	x: 20,
    fun: obj.log
}
target.fun() // 这里又会输出什么呢?

没有会输出:20;

是不是感觉找到一点门道了?this跟它在什么地方定义并没有关系,而是跟它执行时候的主体有关。

构造函数中的this

function Person() {
	this.name = '张三'
   this.fn = function() {
   	console.log(this.name)
   }
}
var person = new Person();

构造函数这里的this,它指向的是 person 这个实例;所以这里会输出张三

但是,总有一些特殊情况

function Person() {
	this.name = '张三'
   this.fn = function() {
   	console.log(this.name)
   }
}
Person.prototype.getName = function() {
	// 原型上的方法this就不是定是实例了,主要看执行的时候,“点”前面的内容
	console.log(this);
}
var person = new Person();
person.getName() // 实例person
person.__proto__.getName() // person.__proto__
Person.prototype.getName() // Person.prototype

这里是可以说是另一个叫原型链的高深话题了(或许可以作为下一次文章的主题)

call和apply、bind

var name = '李四';
var obj = {
	name: '张三'
}
var fun = function() {
	console.log(this.name)
}
fun.call(obj);

这里将输出张三

使用callapplybind将会改变this为它们的第一个参数。

尾声

以上这些是从使用层面上,自己的一些浅显的认识!其实还可以从ES规范层面去解读this,但确实有点太高深了。如果有兴趣大家可以看一下讶羽大神的这篇文章!