理解 this,最好的方式是区分被使用的三种类型的位置:
函数内部:this 是一个额外的隐式的参数。
函数外(顶层作用域):this 在浏览器中指向全局对象,Node.js中指向一个模块的暴露接口。
在传递给 eval() 的字符串中:eval() 也许会取得当前 this 的值,或者是将其设置为全局对象,取决于是直接或者间接的调用。
来看一下各个类型。
1. 在函数内部的 this
这是 this 一种最常用的方式,因为在 JavaScript 中,函数以三种不同的角色代表了所有的可调用的结构形式。
确切的函数(this 在松散模式中为全局对象,在严格模式中为 undefined )
构造函数(this 指向新创建的实例)
方法(this 指向方法调用的接受者)
在函数中,this 被常常认为是一个额外的隐式的参数。
1.1 在确切的函数中的 this
在确切的函数中,this 的值依赖于其所在的模式:
松散模式:this 指向全局对象(浏览器下为windows)
function sloppyFunc(){
console.log( this === window )
}
sloppyFunc();
严格模式:this 的值为 undefined
function strictFunc(){
"use strict";
console.log( this === undefined );
}
strictFunc();
就是说,this 是一个隐式的,设置有默认值(window 或者 undefined)的参数。但是,你可以使一个函数通过 call() 或者 apply() 调用来明确的指定 this 的值。
function func( arg1, arg2 ){
console.log( this );
console.log( arg1 );
console.log( arg2 );
}
func.call( { a:'a' } , 'b', 'c' );
// Object {a: "a"}
// b
// c
func.apply( { a:'a' } , [ 'b', 'c' ]);
// Object {a: "a"}
// b
1.2 在构造函数中的 this
你通过 new 操作符来调用的函数即是构造函数,该操作符创建一个新的对象,并把它通过 this 传递给构造函数:
var savedThis;
function Constr(){
savedThis = this;
}
var inst = new Constr();
console.log( savedThis === inst );
new 操作符使用 JavaScript 实现大致如下(一个更为准确复杂的实现 http://speakingjs.com/es5/ch17.html#_the_new_operator_implemented_in_javascript):
function newOperator( Constr, arrayWithArgs ){
var thisValue = Object.creat( Constr.prototype );
Constr.apply( thisValue, arrayWithArgs );
return thisValue;
}