this指向的问题以及call()、apply()、bind()修改this指向
1、this指向常见的情形
this的理解只需要记住: 它是指向的最后一次被调用的对象
情形一:没有对象调用的情况
var name = 'global';
function fn() {
var name = 'inner';
console.log(this.name); // global this指向的是最后一次被调用的对象!
}
fn(); // 等价于 window.fn(); 因此指向的是window全局
情形二:有对象去调用
对象去调用方法,this指向的最后一次调用的对象。
var name = 'global';
var b = {
name: 'b的name',
fn() {
console.log(this.name);
}
}
b.fn(); // 打印的是 'b的name'
情形三:this只会指向最后一次调用的对象
var name = 'global';
var c = {
name: 'c的name',
fn() {
console.log(this.name);
}
}
window.c.fn();
情形四:当最后一次调用的对象内部没有该属性时
var name = 'global';
var d = {
fn() {
console.log(this.name);
}
}
window.d.fn();
情形五:比较 坑!的情形
把e中的fn()赋值给了f,但是f并没有对象去调用,此时依旧为window.f()
var name = 'global';
var e = {
name: 'e的name',
fn() {
console.log(this.name);
}
}
var f = e.fn;
f();
情形六:
demo方法被window调用,因此,内部的this指向依旧是window,内部函数fn()等价于this.fn()因此,打印的结果是global
var name = 'global';
function demo() {
var name = 'g的name';
fn();
function fn() {
console.log(this.name);
}
}
demo();
2、改变this的指向一:ES6中的箭头函数
ES6中的箭头函数是没有this指向的,如果在箭头函数中使用this,那么它指向的是上下文对象。
function Foo(){
this.name = "Foo的name"
}
// 在原型对象上新增方法
Foo.prototype.getName = function(){
console.log('getName打印的姓名:',this.name)
}
Foo.prototype.putName = function(){
setTimeout(function(){
this.getName()
},100)
}
var f = new Foo();
f.putName();
这种情况下在setTimeout内部console.log
一下this
发现指向的是全局对象window,这是因为ES5的写法带来的影响,如果换成ES6的箭头函数就会解决此类问题。
Foo.prototype.putName = function(){
setTimeout(() => {
console.log(this);
this.getName()
},100)
}
这样指向就修改正确了。
3、改变this的指向二:apply()
fn.apply(target, [argumentsList])
- target:函数调用时绑定的这个对象
- argumentsList:函数调用时预期的实参列表,该参数应该是一个类数组的对象
同样的使用之前的测试案例
function Foo(){
this.name = "Foo的name"
}
// 在原型对象上新增方法
Foo.prototype.getName = function(){
console.log('getName打印的姓名:',this.name)
}
Foo.prototype.putName = function(){
setTimeout(function(){
this.getName()
},100)
}
var f = new Foo();
f.putName();
目前的this指向的是window全局对象,可以在函数末尾添加apply(f)去指定函数调用的实例对象f.
Foo.prototype.putName = function(){
setTimeout(function(){
console.log(this);
this.getName()
}.apply(f),100)
}
修改后的结果指向依旧是正确的
4、改变this的指向三:call()
Foo.prototype.putName = function(){
setTimeout(function(){
console.log(this);
this.getName()
}.call(f),100)
}
5、改变this的指向四:bind()
Foo.prototype.putName = function(){
setTimeout(function(){
console.log(this);
this.getName()
}.bind(f)(),100)
}
作者:听书先生
原文链接:https://www.jianshu.com/p/1852af464ef7