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
,但确实有点太高深了。如果有兴趣大家可以看一下讶羽大神的这篇文章!