关于this

107 阅读2分钟

1 误解

1.1 误解一:this 理解成指向函数自身

function foo(num) {
    console.log( "foo: " + num );
    // 记录 foo 被调用的次数
    this.count++; 
}
foo.count = 0;
var i;
for (i=0; i<10; i++) { 
    if (i > 5) {
        foo( i ); 
    }
}
// foo 被调用了多少次?
console.log( foo.count ); // 0 

//因为this并不指向函数本身

1.2 误解二:this 指向函数的作用域

function foo() { 
    var a = 2;
    this.bar();
}
function bar() { 
    console.log( this.a );
}
foo(); // ReferenceError: a is not defined

//bar中的this不指向bar所在的foo,所以取不到a

划重点:

  • this 是在运行时进行绑定的,并不是在编写时绑定。
  • 它的上下文取决于函数调用时的各种条件。
  • this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

2 调用位置

this最终指向的是调用它的对象。只能调用位置有关,和创建位置无关。

  • 一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window
function a(){
    let user = "Hello";
    console.log(this.user); //undefined
    console.log(this); //Window--指向调用位置,全局
}
a(); //全局没有user,所以undefined
  • 一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象
let o = {
    user:"Hello",
    fn:function(){
        console.log(this.user);  //Hello
    }
}
o.fn(); //this指向o
  • 如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
let o = {
    a:1,
    b:{
        a:2,
        fn:function(){
            console.log(this.a); //2
            //多层调用a.b.c,指向上一级b而非最外层a
        }
    }
}
o.b.fn();

拓展一下:
let o = {
    a:1,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

易错点:

let o = {
    a:1,
    b:{
        a:2,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
let j = o.b.fn;
j(); //j指向fn,this指向window

构造函数可以改变this的指向。

  • new关键字改变this的指向,将this指向创建的对象
function Fn(){
    this.user = "Hello";
}
var a = new Fn();
console.log(a.user); //Hello
  • 如果构造函数返回一个对象,那么this指向返回的对象
function fn()  
{  
    this.user = 'Hello';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined

function fn()  
{  
    this.user = 'Hello';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined
  • 如果返回值不是一个对象那么this还是指向函数的实例。
function fn()  
{  
    this.user = 'Hello';  
    return 1;
}
var a = new fn;  
console.log(a.user); //Hello
function fn()  
{  
    this.user = 'Hello';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //Hello
  • 特例:null也是对象,但是this还是指向函数的实例。
function fn()  
{  
    this.user = '追梦子';  
    return null;
}
var a = new fn;  
console.log(a.user); //追梦子
  • new关键字会创建一个空的对象,然后自动调用apply方法,将this指向这个空对象,然后函数内部的this就会被这个空的对象替代。
function fn(){
    this.num = 1;
}
var a = new fn();
console.log(a.num); //1

3 绑定规则

4 优先级