JS之this

October 30, 2021

相关阅读

JavaScript 的 this 原理 - 阮一峰

this指向问题

首先来看下面的例子,不同的写法,可能有不同的结果

var obj = {
  foo: function() { console.log(this.bar); },
  bar: 1
};
var foo = obj.foo;
var bar = 2;
obj.foo() // 1
foo() // 2

造成不同结果的原因,在于函数里使用到了this,obj.foo()是在obj的环境执行,因此拿到的是obj的bar。而一旦var foo = obj.foo, foo()就变成在全局环境执行。

那函数的运行环境到底是怎么决定的?

var obj = {foo: 5};

上面的代码将一个对象赋值给变量obj,JS引擎会先在内存里生成一个对象{foo: 5},再把内存地址赋值给obj。 原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。上面例子的foo属性,实际上是以下面的形式存在的: obj -> foo -> [[value]]:5 [[writable]]:true [[enumerable]]: true [[configurable]]: true

那如果属性的值是一个函数,like:

var obj = { foo: function() {}};

这时引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性value属性 hw-os-app 由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行, 而this就是用于在函数体内部获得当前的运行环境

var f = function() {
  console.log(this.x);
}
var x=1;
var obj = {
  f:f,
  x:2
}

//单独执行
f(); // 1
//obj环境执行
obj.f(); //2

上述代码中,函数f在全局环境执行,this.x指向全局环境的x hw-os-app 在obj环境执行,this.x指向obj.x hw-os-app

this上下文

全局上下文

无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this都指向全局对象, 严格模式时指向undefined,非严格模式下,自动指向全局对象(浏览器中就是window)

函数上下文

在函数内部,this的值取决于函数被调用的方式。 函数的调用方式有哪些:

  • 在全局环境或是普通函数中直接调用
  • 作为对象的方法
  • 使用apply和call
  • 作为构造函数

直接调用

var a = 1;
var obj  =  {
    a: 2,
      b: function () {
        function fun() {
          return this.a
        }
       console.log(fun());
    }
} 
obj.b();//1

fun函数虽然在obj.b方法中定义,但它还是一个普通函数,直接调用在非严格模式下指向全局对象。 当函数独立调用的时候,在严格模式下它的this指向undefined,在非严格模式下,当this指向undefined的时候,自动指向全局对象(浏览器中就是window)。

作为对象的方法

var a = 1;
var obj = {
  a: 2,
  b: function() {
    return this.a;
  }
}
console.log(obj.b())//2
var t = obj.b;
console.log(t());//1

作为对象的方法调用-〉obj.b(),这个时候this指向调用它的对象,就是obj。var t = obj.b时,这个时候就不是作为对象的方法调用,相当于函数独立调用。

使用call和apply

改变函数执行上下文

作为构造函数

this代表它即将new出来的对象

箭头函数

箭头函数,不可以用call和apply改变this, 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值


Profile picture

百事可乐

Let it snow, let it snow, let it snow