这个内部原型函数等于窗口而不是对象实例 [英] this inside prototype function equal to window instead of object instance
问题描述
在 HeadDirective.prototype.link
的以下代码中, this
等于全局 window
对象,而不是 HeadDirective
实例。我的理解是,原型函数中 this
的值本身就是包含对象。
In the following code in HeadDirective.prototype.link
, this
is equal to the global window
object rather than the HeadDirective
instance. My understanding is that the value of this
inside a prototype function is the containing object itself.
var HeadDirective = (function () {
function HeadDirective($rootScope, $compile) {
this.$rootScope = $rootScope;
this.$compile = $compile;
this.restrict = 'E';
}
HeadDirective.prototype.link = function (scope, elem) {
var html = '<link rel="stylesheet" ng-repeat="cssUrl in routeStyles" ng-href="{{cssUrl}}" />';
elem.append(this.$compile(html)(scope));
scope.routeStyles = [];
this.$rootScope.$on('$routeChangeStart', function (e, next, current) {
if (next && next.$$route && next.$$route.css) {
if (!Array.isArray(next.$$route.css)) {
next.$$route.css = [next.$$route.css];
}
angular.forEach(next.$$route.css, function (sheet) {
scope.routeStyles.push(sheet);
});
}
});
this.$rootScope.$on('$routeChangeSuccess', function (e, next, current) {
if (current && current.$$route && current.$$route.css) {
if (!Array.isArray(current.$$route.css)) {
current.$$route.css = [current.$$route.css];
}
angular.forEach(current.$$route.css, function (sheet) {
scope.routeStyles.splice(scope.routeStyles.indexOf(sheet), 1);
});
}
});
};
return HeadDirective;
})();
directives.directive('head', [
'$rootScope', '$compile', function ($rootScope, $compile) {
return new HeadDirective($rootScope, $compile);
}]);
上面的代码是从以下TypeScript生成的:
The above code was generated from the following TypeScript:
class HeadDirective implements ng.IDirective {
constructor(private $rootScope: ng.IRootScopeService, private $compile: ng.ICompileService) {}
link(scope: IScope, elem: JQuery): void {
var html = '<link rel="stylesheet" ng-repeat="cssUrl in routeStyles" ng-href="{{cssUrl}}" />';
elem.append(this.$compile(html)(scope));
scope.routeStyles = [];
this.$rootScope.$on('$routeChangeStart', (e: ng.IAngularEvent, next?: IRoute, current?: IRoute): any => {
if(next && next.$$route && next.$$route.css){
if(!Array.isArray(next.$$route.css)){
next.$$route.css = [next.$$route.css];
}
angular.forEach(next.$$route.css, (sheet: string) => {
scope.routeStyles.push(sheet);
});
}
});
this.$rootScope.$on('$routeChangeSuccess', (e: ng.IAngularEvent, next?: IRoute, current?: IRoute): any => {
if(current && current.$$route && current.$$route.css){
if(!Array.isArray(current.$$route.css)){
current.$$route.css = [current.$$route.css];
}
angular.forEach(current.$$route.css, (sheet) => {
scope.routeStyles.splice(scope.routeStyles.indexOf(sheet), 1);
});
}
});
}
restrict = 'E';
}
directives.directive('head', ['$rootScope','$compile', ($rootScope: ng.IRootScopeService, $compile: ng.ICompileService): ng.IDirective =>{
return new HeadDirective($rootScope, $compile);
}]);
根据最新的TypeScript语言规范:
According to the latest TypeScript language specification:
表达式中 this
的类型取决于引用发生的位置:
The type of
this
in an expression depends on the location in which the reference takes place:
- 在构造函数中,实例成员函数,实例成员访问器或实例成员变量初始值设定项
this
是包含类的类实例类型。 - 在静态成员函数或静态成员访问器中,
this
类型是包含类的构造函数类型。 - 在函数声明或标准函数表达式中,
此
是Any类型。 - 在全局模块中,
此
的类型为Any。
- In a constructor, instance member function, instance member accessor, or instance member variable initializer,
this
is of the class instance type of the containing class. - In a static member function or static member accessor, the type of
this
is the constructor function type of the containing class. - In a function declaration or a standard function expression,
this
is of type Any. - In the global module,
this
is of type Any.
在所有其他上下文中,引用此是编译时错误。
In all other contexts it is a compile-time error to reference this.
TypeScript语言规范非常明确。在成员函数(已编译为原型函数)中, this
引用类实例。显然这不是我所看到的。
The TypeScript language specification is quite clear. Inside a member function (which is compiled into a prototype function), this
refers to the class instance. This is obviously not what I'm seeing.
有什么想法吗? Browserify会干扰 this
吗?
Any ideas? Could Browserify be interfering with this
?
推荐答案
此
关键字与上下文高度相关。例如,如果事件调用了方法,则此
将成为事件目标的对象。
The this
keyword is highly contextual. If a method is called by an event, this
will be the object that is the event target, for example.
您可以通过将 this
填充到变量中或使用JavaScript 调用$ c来解决 this 问题。 $ c>(或
apply
)方法来绑定 this
的范围。
You can get around this problem by shimmying this
into a variable, or by using the JavaScript call
(or apply
) methods to bind the scope of this
.
简短示例...这是前提:
Short example... here is the premise:
class MyClass {
constructor(private myProp: string) {
}
myMethod() {
alert(this.myProp);
}
}
var myClass = new MyClass('Test');
// 'Test'
myClass.myMethod();
// undefined
window.setTimeout(myClass.myMethod, 1000);
解决方案一-箭头语法
在TypeScript的箭头语法会自动为您填充 this
到一个名为 _this
的变量中,并替代arrow函数中的用法。因此,这将解决上面的 undefined
问题,并提醒 Test
。
Solution One - Arrow Syntax
In TypeScript the arrow syntax will shimmy this
into a variable called _this
automatically for you and substitute usages inside the arrow function... So this will solve the undefined
issue above and instead alert Test
.
class MyClass {
constructor(private myProp: string) {
}
public myMethod = () => {
alert(this.myProp);
}
}
解决方案二-调用方法
您可以使用 call
方法将上下文 this
替换为任何对象例如,在下面的示例中,我们将其重置为 myClass
实例。
Solution Two - Call Method
You can use the call
method to replace the contextual this
with any object you like, in the example below we reset it to be the myClass
instance.
无论您是否编写TypeScript,此方法都有效还是普通的JavaScript ...而第一个解决方案实际上是TypeScript解决方案。
This works whether you are writing TypeScript or plain JavaScript... whereas the first solution is really a TypeScript solution.
window.setTimeout(function() { myClass.myMethod.call(myClass) }, 1000);
或更短(要清楚,此处箭头功能的使用与scope-只是一种较短的语法箭头函数仅在其中包含 this
时才影响范围):
Or to be shorter (to be clear, the use of the arrow function here has nothing to do with scope - it is just a shorter syntax arrow functions only affect scope if you have this
inside of them):
window.setTimeout(() => myClass.myMethod.call(myClass), 1000);
这篇关于这个内部原型函数等于窗口而不是对象实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!