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);
这里将输出张三
使用call和apply、bind将会改变this为它们的第一个参数。
尾声
以上这些是从使用层面上,自己的一些浅显的认识!其实还可以从ES规范层面去解读this,但确实有点太高深了。如果有兴趣大家可以看一下讶羽大神的这篇文章!