在Javascript中,this的概念比较复杂。除了在面向对象编程中,this还是随处可用的。这篇文章介绍了this的工作原理,它会造成什么样的问题以及this的相关例子。要根据this所在的位置来理解它,情况大概可以分为3种:
1、在函数中:this通常是一个隐含的参数。
2、在函数外(顶级作用域中):在浏览器中this指的是全局对象;在Node.js中指的是模块(module)的导出(exports)。
3、传递到eval()中的字符串:如果eval()是被直接调用的,this指的是当前对象;如果eval()是被间接调用的,this就是指全局对象。
对这几个分类,我们做了相应的测试:
函数基本可以代表JS中所有可被调用的结构,所以这是也最常见的使用this的场景,而函数又能被子分为下列三种角色:
1.1在实函数中的this
在实函数中,this的值是取决于它所处的上下文的模式。
Sloppy模式:this指的是全局对象(在浏览器中就是window)。
1234 | function sloppyFunc() {
console.log( this === window); // true } sloppyFunc(); |
Strict模式:this的值是undefined。
12345 | function strictFunc() {
'use strict' ; console.log( this === undefined); // true } strictFunc(); |
this是函数的隐含参数,所以它的值总是相同的。不过你是可以通过使用call()或者apply()的方法显示地定义好this的值的。
1234567 | function func(arg1, arg2) {
console.log( this ); // 1
console.log(arg1); // 2
console.log(arg2); // 3 } func.call(1, 2, 3); // (this, arg1, arg2) func.apply(1, [2, 3]); // (this, arrayWithArgs) |
1.2构造器中的this
你可以通过new将一个函数当做一个构造器来使用。new操作创建了一个新的对象,并将这个对象通过this传入构造器中。
123456 | var savedThis; function Constr() {
savedThis = this ; } var inst = new Constr(); console.log(savedThis === inst); // true |
JS中new操作的实现原理大概如下面的代码所示(更准确的实现请看这里,这个实现也比较复杂一些):
12345 | function newOperator(Constr, arrayWithArgs) {
var thisValue = Object.create(Constr.PRototype);
Constr.apply(thisValue, arrayWithArgs);
return thisValue; } |
1.3方法中的this
在方法中this的用法更倾向于传统的面向对象语言:this指向的接收方,也就是包含有这个方法的对象。
123456 | var obj = {
method: function () {
console.log( this === obj); // true
} } obj.method(); |
在浏览器中,作用域就是全局作用域,this指的就是这个全局对象(就像window):
123 | <script>
console.log( this === window); // true </script> |
在Node.js中,你通常都是在module中执行函数的。因此,顶级作用域是个很特别的模块作用域(module scope):
1234567 | //`global`(not`window`) refers to global object: console.log(Math === global.Math); // true // `this` doesn’t refer to the global object: console.log( this !== global); // true // `this` refers to a module’s exports: console.log( this === module.exports); // true |
eval()可以被直接(通过调用这个函数名’eval’)或者间接(通过别的方式调用,比如call())地调用。要了解更多细节,请看这里。
123456789101112131415161718192021222324252627 | // Real functions function sloppyFunc() {
console.log(eval( 'this' ) === window); // true } sloppyFunc(); function strictFunc() {
|