this的指向
this的指向始终坚持一个原理:“this谁调用他,他就指向谁”,切记这句话。下面看几个例子。
var obj = {
name: 'wangwu',
say: function() {
console.log(this.name);
}
}
obj.say() // wangwu
最基本的使用,函数say是obj调用的,函数中的this指向obj,所以打印的是wangwu
let name = 'zhaosi'
const obj = {
name: 'laotie',
say: function() {
console.log(this.name);
}
}
const func = obj.say
func() // zhaosi
把say赋给变量func,然后调用func,前面没有调用对象,那么此时的调用对象就是全局对象window,因此this指向window,所以打印zhaosi。
let name = 'lisi'
const obj = {
name: 'ppd',
say: function() {
console.log(this.name);
}
}
window.obj.say() // ppd
this谁调用他,他就指向谁,这里虽然前面加了个window,但是最后调用者还是obj,因此this指向obj。
可以看出:this的指向并不是在创建的时候就可以确定的。this永远指向最后调用它的那个对象
let name = 'xdm'
const obj = {
name: 'zhaoliu',
say: function() {
console.log(this.name); // zhaoliu
func()
function func() {
console.log(this.name); // xdm
}
},
}
obj.say()
say的调用者是obj,say函数内部的this就指向obj,因此第一次打印zhaoliu
。再调用func,此时func的调用者是window,func函数内部的this就指向window,因此第二次打印xdm
改变this指向有以下几种方法:
使用箭头函数
使用apply、call、bind改变this指向
箭头函数中没有this绑定,必须通过查找作用域链来决定其值。如果箭头函数被非箭头函数包含,则this绑定的是上一级非箭头函数的this
let name = 'xdm'
const obj = {
name: 'zhaoliu',
func: function() {
console.log(this.name);
},
fn: function() {
setTimeout(function() {
this.fn()
}, 1000)
}
}
obj.func2() // this.fn is not a function
上面代码,调用fn报错,因为最终调用setTimeout
的对象是window,函数里的this指向window,而window中并没有fn,所以报错。
apply、call 、 bind
apply和call 和bind 都是用来改变this指向的,三个都是绑定this的指向 到第一参数对象,用法稍微有点不同
call bind 以参数列表方式传参
函数.call(需要绑定的对象, 参数1, 参数2, ...) //没有返回值
bind() 方法创建一个新的函数,在 bind() 被调用时,
这个新函数的 this 被指定为 bind() 的第一个参数,
而其余参数将作为新函数的参数,供调用时使用。
函数.bind(需要绑定的对象, 参数1, 参数2, ...) //返回一个新函数
this.x = 9; // 在浏览器中,this 指向全局的 "window" 对象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回 9 - 因为函数是在全局作用域中调用的
// 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
apply 以数组方式传参/伪数组 用的是伪数组的 数组特征
apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数