如下内容只针对非严格模式,严格模式区不说了
若是看过《JavaScript高级程序设计(第3版)》的人都应该有印象,里面关于this对象是这么形容的segmentfault
this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被做为某个对象的方法调用时,this 等于那个对象。不过,匿名函数的执行环境具备全局性,所以其 this 对象一般指向 window。
示例以下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
目前为止,一切都符合预期表现。而后咱们再看些复杂点的写法。函数
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
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
带着疑问咱们直接看例子对象
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也是指向全局的.原型链
而后看看常常会用到的函数return出的this指向get
var a = 10, obj = { a: 20, log: function () { return function () { console.log(this.a); //指向?? } } }; obj.log()(); //10
衹要基础稍好也能理解,由于obj.log()返回一个匿名函数,而后至关于在全局下再调用匿名函数,所以this直接指向全局了。书里官方点的解释就是
每一个函数在被调用时都会自动取得两个特殊变量:this
和arguments
。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,所以永远不可能直接访问外部函数中的这两个变量(例子是指obj)
须要注意的是若是没有明确指向全局的话this实际上都是指向undefined的,衹是非严格模式下,它会被自动指向全局对象。
function log() { 'use strict'; console.log(this === window); } log(); // 独立调用false window.log(); // window下调用 true
书里还提到一个挺有意思的写法
var a = 10, obj = { a: 20, log: function () { console.log(this.a); //指向?? } }; (obj.log = obj.log)(); //先赋值再调用 10
你会发现竟然this也指向全局了。
由于代码先执行了一条赋值语句,而后再调用赋值后的结果。由于这个赋值表达式的值是函数自己,因此 this 的值不能获得维持,结果就返回了10。
若是是做为构造函数
使用的状况下
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运算符,构造函数与原型链一些理解
还有种状况是经过call
或apply
修改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指向方法指定对象