'this' in function inside prototype function
我基本上有一个对象,通过它的原型扩展了一个函数。在该函数内部,存在另一个函数,但是当在这个嵌套函数中使用
例如,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var sampleObject = function() { this.foo = 123; } sampleObject.prototype.getFoo = function() { var nested = function() { return this.foo; } return nested(); } var test = new sampleObject(); window.alert(test.getFoo()); // undefined |
1 2 3 4 5 6 7 | sampleObject.prototype.getFoo = function() { var me = this; var nested = function() { return me.foo; } return nested; } |
通过在局部变量中保存
这方面的常见工作是使用闭包
1 2 3 4 5 6 7 | sampleObject.prototype.getFoo = function() { var _this = this; var nested = function() { return _this.foo; } return nested(); } |
一些库添加方法来自动执行此操作
- 原型添加了function.bind(http://prototypejs.org/doc/latest/language/function/prototype/bind/)
- ext添加function.createdelegate(http://www.sencha.com/learn/manual:utilities:function createdelegate)
- javascript 1.8.5添加了function.bind(https://developer.mozilla.org/en/javascript/reference/global_objects/function/bind)
在您的示例中,"this"指的是window对象,因为您在调用嵌套函数时没有指定另一个上下文,并且由于window.foo未定义而得到未发现。
你可以用三种方法来解决这个问题。
1-使用变量存储外部此-最常用的方法1 2 3 4 5 6 7 | sampleObject.prototype.getFoo = function() { var _this = this; var nested = function() { return _this.foo; } return nested(); } |
2-使用将外部"this"绑定到内部的绑定方法
1 2 3 4 5 6 | sampleObject.prototype.getFoo = function() { var nested = function() { return this.foo; }.bind(this); return nested(); } |
3-使用可将上下文传递给函数的调用方法
1 2 3 4 5 6 | SampleObject.prototype.getFoo = function() { var nested = function() { return this.foo; }; return nested.call(this); } |
DR
使用箭头功能。自ECMAScript 6起提供:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var sampleObject = function() { this.foo = 123; } sampleObject.prototype.getFoo = function() { var nested = () => { // Changed this line. return this.foo; } return nested(); } var test = new sampleObject(); window.alert(test.getFoo()); |
这是arrow函数的主要优点之一。您的案件在"EDOCX1不具有约束力"〔0〕一节中有描述。引用说明:
Until arrow functions, every new function defined its own
this value [...]
An arrow function does not create its ownthis context, sothis has the original meaning from the enclosing context.
除了向
了解变量的范围很重要,因为它可能会产生意外的结果。
这是一个古老的问题,但为了完整性,我给出了另一个解决方案。另一种方法涉及函数绑定。
1 2 3 4 5 6 | sampleObject.prototype.getFoo = function() { var nested = function() { return this.foo; } return nested.bind(this)(); } |
ES6的一种方法是使用箭头函数。基本上,当您使用箭头函数时,它不会创建自己的"this"上下文。因此,使用"this"将引用父函数的上下文。代码的外观如下:
1 2 3 4 5 6 | sampleObject.prototype.getFoo = function() { const nested = () => { return this.foo; //"this" refers to parent function's context } return nested; } |
这是javascript上的一个已知缺陷。通常的模式是将其分配给外部函数中的另一个变量(通常是self),然后从内部函数访问self。这是可行的。