Javascript中this基础应用

前言

如下内容只针对非严格模式,严格模式区不说了
若是看过《JavaScript高级程序设计(第3版)》的人都应该有印象,里面关于this对象是这么形容的segmentfault

this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被做为某个对象的方法调用时,this 等于那个对象。不过,匿名函数的执行环境具备全局性,所以其 this 对象一般指向 window。

demo1

示例以下app

var a = 10,
  obj = {
    a: 20
  };

function log() {
  var a = 30;
  console.log(this.a); //依然指向全局
};

console.log(this.a); // 全局
log(); //方法
log.call(obj); //指向obj

;
(function () {
  console.log(this.a) //匿名函数
})()

// 10
// 10
// 20
// 10

目前为止,一切都符合预期表现。而后咱们再看些复杂点的写法。函数

demo2

var a = 10,
  obj = {
    a: 20,
    log: function () {
      console.log(this.a); //指向obj
    }
  };

function log() {
  function _log() {
    console.log(this.a); //指向全局
  };
  _log();
};

obj.log(); //调用对象方法
log(); //调用方法内部方法

// 20
// 10

虽然有点绕,可是仍是能够明白的,this指向调用方法该对象,匿名函数this指向全局
看到这里咱们好像已经大概明白this是怎么一回事了,而后咱们再写复杂点this

demo3

var a = 10,
  obj = {
    a: 20,
    b: this.a + 30
  };
console.log(obj.b); // 40

是否是又猛的怀疑人生了?明明应该this是指向obj得出50,为何会指向全局得出40的!?
想一想上面说的当函数被做为某个对象的方法调用时, this 等于那个对象。难道属性值又是另外一回事?
带着疑问咱们直接打印出this看看设计

var a = 10,
  obj = {
    a: 20,
    b: this
  };
console.log(obj.b === window); //true

因此属性值里的this真的指向全局,因而咱们能够假设得出一个结论:当函数被做为某个对象的方法调用时, this 等于那个对象,而某个对象的属性值的this是直接指向全局的
听起来好拗口,是否是意思对象的方法this指向对象,属性值指向全局!?code

demo4

带着疑问咱们直接看例子对象

var a = 10,
  obj = {
    a: 20,
    log: function () {
      console.log(this.a);
    }
  };
var fn = obj.log;
fn(); //调用赋值方法10

正如前面所说,当函数被做为某个对象的方法调用时, this 等于那个对象。若是不是该对象直接调用时,this指向调用对象。
基于这个结论,即便中间通过几层函数调用也同样的ip

var a = 10,
  obj = {
    a: 20,
    log: function () {
      console.log(this.a); //指向obj
    }
  };

function all_log(fn) {
  fn();
}

all_log(obj.log); // 10

看到了吧,即便通过一个中间函数调用,实际至关于window调用对象方法,因此this也是指向全局的.原型链

demo5

而后看看常常会用到的函数return出的this指向get

var a = 10,
  obj = {
    a: 20,
    log: function () {
      return function () {
        console.log(this.a); //指向??
      }
    }
  };
obj.log()(); //10

衹要基础稍好也能理解,由于obj.log()返回一个匿名函数,而后至关于在全局下再调用匿名函数,所以this直接指向全局了。书里官方点的解释就是

每一个函数在被调用时都会自动取得两个特殊变量: thisarguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,所以永远不可能直接访问外部函数中的这两个变量(例子是指obj)

须要注意的是若是没有明确指向全局的话this实际上都是指向undefined的,衹是非严格模式下,它会被自动指向全局对象。

function log() {
  'use strict';
  console.log(this === window);
}

log(); // 独立调用false
window.log(); // window下调用 true

demo6

书里还提到一个挺有意思的写法

var a = 10,
  obj = {
    a: 20,
    log: function () {
      console.log(this.a); //指向??
    }
  };
(obj.log = obj.log)(); //先赋值再调用 10

你会发现竟然this也指向全局了。
由于代码先执行了一条赋值语句,而后再调用赋值后的结果。由于这个赋值表达式的值是函数自己,因此 this 的值不能获得维持,结果就返回了10。

demo7

若是是做为构造函数使用的状况下

function Person() {
  this.name = 'mike';
  this.log = function () {
    console.log(this);
  }
};

var man = new Person();
man.log();//Person {name: "mike", log: function}

里面的this是指向new出来的对象,详情能够看看我以前写的博文关于Javascript中的new运算符,构造函数与原型链一些理解

demo8

还有种状况是经过callapply修改this指向,它会强制指向方法的第一个参数

var a = 10,
  obj = {
    a: 20
  };

function log() {
  console.log(this.a);
};

log.call(obj); //指向obj
log.apply(obj); //指向obj

基于上面的状况,咱们能够得出几个结论

1, this 对象是在运行时基于函数的执行环境绑定的2, 若是没有明确指向全局的话this实际上都是指向undefined的,衹是非严格模式下,它会被自动指向全局对象3, 当函数被做为某个对象的方法调用时,this 等于那个对象4, 当某个对象的属性值里的this是直接指向全局对象5, 匿名函数的执行环境具备全局性,所以其 this 对象一般指向全局对象6, 构造函数中的this会指向它实例化对象7, call或apply方法能强制修改this指向方法指定对象

相关文章
相关标签/搜索