this的指向

this的指向,是在函数被调用的时候确定的。

在ES5中this一直是很神奇的东西,因为如果不是很理解的话,this是真的会弄崩心态的(所以ES6的箭头函数真是很友好了)

最近也有在准备笔试,想把基础夯实,所以今天写一篇关于this指向的blog。


在开头,我们说this的指向是在函数被调用的时候确定的。这是因为this的指向在执行上下文被创建时确定的。就是说这段this代码,他运行在不同的环境,this就能指向不同的对象。

先来看一个例子

var x = 10;
var obj = {
    x: 20
}

function demo () {
    console.log(this.x);
}

fn(); // 10
fn.call(obj); // 20

第一个fn()中,fn()是独立调用的,我调用我自己,所以this指向自己为undefine,但是是为非严格模式,this指向undefined时会自动指向全局变量。而第二个fn.call(obj)可以理解为,fn让obj作为它的调用者,所以this指向调用者obj,所以最后输出为20。

再来看一个例子:

'use strict';
var a = 20;
function foo () {
    var a = 1;
    var obj = {
        a: 10,
        c: this.a + 20,
        fn: function () {
            return this.a;
        }
    }
    return obj.fn;

}
console.log(foo());
console.log(window.foo()); 

现在按照上面的思路来推一下

由于foo()是独立调用的,那么它之中的this是指向undefine的,所以第一句console.log(foo())报错:Cannot read property 'a' of undefined.

而第二句,foo()有一个调用者是window,所以this全部指向window,最后是全局的a:20 + 20 输出40.

现在对独立调用和被调用应该有了一个大致的理解,对于this的指向也有了初步的认识。


我们再看这一个例子:

var a = 20;
function foo1(){
  var obj = {
    a: 10,
    getA: function () {
        return this.a;
    }
  }
  return obj.getA();
}
console.log(foo1());//10
function foo2(){
  var obj = {
    a: 10,
    getA: function () {
        return this.a;
    }
  }
  return obj.getA;
}
console.log(foo2()());//20

这个例子说明,我们必须弄明白真正的调用者是谁,foo1中,是直接return this.a,this指向了getA的调用者obj。而foo2(),相当于有一个 var tmp = obj.getA()的操作,函数的调用真正的调用者是tmp自己,这个是独立调用,指向Undefine.


在ES6中,由于箭头函数的存在,让this由动态变成了静态

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

对于这个ES6入门中的例子,我们可以看到,如果是普通的函数的话,由于setTimeout是异步的,等待0.1s后运行匿名函数打印id时,this的执行上下文已经不是foo,而是在全局中独立调用,指向undefined。 这里我一开始觉得是应该是独立调用,指向undefined,只是因为没有用严格模式,后来我查了一下,应该不是因为this的执行上下文,而是setTimeout中的this指针会默认指向window

posted @ 2019-06-18 10:54  Kiznaiver  阅读(203)  评论(0编辑  收藏  举报