这个内部原型函数等于窗口而不是对象实例 [英] this inside prototype function equal to window instead of object instance

查看:55
本文介绍了这个内部原型函数等于窗口而不是对象实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 调用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆