Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/458.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 打字稿-she';我们必须拥有它吗?(其中it==全局范围)_Javascript_Angularjs_Scope_Typescript - Fatal编程技术网

Javascript 打字稿-she';我们必须拥有它吗?(其中it==全局范围)

Javascript 打字稿-she';我们必须拥有它吗?(其中it==全局范围),javascript,angularjs,scope,typescript,Javascript,Angularjs,Scope,Typescript,我正在将Angular应用程序转换为使用TypeScript,但这是一个一般的TypeScript问题,与Angular无关。 角度js文件如下所示: (function () { var app = angular.module('myModule', []); app.controller('myController', ['$scope', function ($scope) { $scope.myNewProperty = "Bob"; } ]);

我正在将Angular应用程序转换为使用TypeScript,但这是一个一般的TypeScript问题,与Angular无关。 角度js文件如下所示:

(function () {
  var app = angular.module('myModule', []);
  app.controller('myController', ['$scope',
    function ($scope) {
      $scope.myNewProperty = "Bob";
    }
  ]);
})();
我已将其转换为可爱的TypeScript类语法:

class myController {
    constructor($scope) {
        $scope.myNewProperty = "Bob";
    }
}

angular.module('myModule', []).controller("myController", myController);
除了生成的JS没有按照JS模块模式进行包装(即在外部匿名函数中),所有工作正常:

所以myController现在是全球性的。如果我将该类放入一个TypeScript模块中,那么js将以模块名作为全局变量生成:

var TsModule;
(function (TsModule) {
    var myController =     (function () {
          app.controller('myController', ['$scope',
            function ($scope) {
              $scope.myNewProperty = "Bob";
            }
          ]);
        })();

    var app = angular.module('myModule', []);
})(TsModule || (TsModule = {}));
如何阻止TypeScript以这种方式污染全局范围?我只想把它包装在一个漂亮的局部范围内。 我在别处看到它说“只需回到旧的JS语法”(即没有TypeScript类)。

但是我们使用TypeScript/is/的全部要点是类语法。TypeScript是否与任何(明智的)知道不走向全局的JS程序员不一致?

快速更新 在最新版本的TypeScript中,您可以在IIFE中嵌套一个类:

(() => {
    class Example {

    }
})();
结果是:

(function () {
    var Example = (function () {
        function Example() {
        }
        return Example;
    }());
})();
原始答案 您可以避免使用AMD或CommonJS等模块模式添加到全局范围。当您使用其中任何一个时,每个TypeScript文件都被视为一个外部模块,不在全局范围内

本例出于本例的目的删除了Angular,但尽管RequireJS将
define
方法添加到global,但您的代码都不在此范围内

MyModule.ts

export class myController {
    constructor($scope) {
        $scope.myNewProperty = "Bob";
    }
}
app.ts

import MyModule = require('MyModule');

var controller = new MyModule.myController('');
HTML


或者。。。如你所知。。。如果您愿意,您仍然可以使用已经在使用的JavaScript来实现这一切-您仍然可以获得自动完成和类型检查,这是即使您没有获得类的主要好处。

您可以简单地将类包装在
模块中。

模块本身是全局的,但如果不导出类,就不必担心用单个模块名污染全局范围

因此,这个类型脚本:

module MyModule {
  class MyClass {
     constructor(){}
  }
}
(function () {
  class MyController {
    static $inject = ['$scope'];
    contructor($scope: ng.IScope & { myNewProperty: string }) {
      $scope.myNewProperty = 'Bob';
    }
  }

  angular.module('myModule', [])
    .controller('MyController', MyController);
})();
将生成以下JS:

var MyModule;
(function (MyModule) {
    var MyClass = (function () {
        function MyClass() {
        }
        return MyClass;
    })();
})(MyModule || (MyModule = {}));

乔希是对的。使用模块。同样,使用grunt或gulp uglifyer可能是一个好主意,它可以选择在构建时将整个应用程序封装在一个闭包中

这不是对你问题的回答,而是一个建议

在侧面注释中,考虑控制器

的语法
module myModule {

    // We export the class so that we can access its interface in tests.
    // The build time gulp or grunt uglify will wrap our app in a closure
    // so that none of these exports will be available outside the app. 
    export class MyController {

         myNewProperty = "bob";

        // Next we will use Angulars $inject annotation to inject a service
        // into our controller. We will make this private so that it can be 
        // used internally.
        static $inject = ['someService'];
        constructor(private someService: ng.ISomeService) {}

        // we can access our class members using 'this'
        doSomething() {
            this.someService.doSomething(this.myNewProperty);
        }

    }

    angular.module('app').controller('MyController', MyController);

}

与此语法一起使用的是controllerAs语法

就像在JavaScript中一样,通过将声明包装在立即调用的函数表达式中,可以完全避免名称空间污染

因此,原始JavaScript:

(function () {
  var app = angular.module('myModule', []);
  app.controller('myController', ['$scope',
    function ($scope) {
      $scope.myNewProperty = "Bob";
    }
  ]);
})();
成为以下类型脚本:

module MyModule {
  class MyClass {
     constructor(){}
  }
}
(function () {
  class MyController {
    static $inject = ['$scope'];
    contructor($scope: ng.IScope & { myNewProperty: string }) {
      $scope.myNewProperty = 'Bob';
    }
  }

  angular.module('myModule', [])
    .controller('MyController', MyController);
})();
请注意,这不会在周围的范围中引入任何名称。实际上,原始JavaScript是完全有效的TypeScript,但它没有利用TypeScript。 还请注意,我对样式进行了轻微的编辑


无论如何,如果您没有使用带有模块加载器的模块,如RequireJS、SystemJS或您拥有的其他模块,那么您仍然可以通过遵循久经考验的IIFE模式来避免名称空间污染。这是我的建议。

我已经有一段时间没有使用TypeScript了,所以我可能会停止使用它,但是您是否尝试过在立即调用的lambda函数中包装上述TypeScript代码<代码>(()=>{//code here…})()我感到很沮丧,但是为所有文件使用一个定义良好的模块名几乎不会影响全局范围。它将在全局范围内创建一个变量,即使这样,如果您不导出类,那么它也永远不会超过一个空对象。这是一个相当小的问题。仅供参考(你可能已经知道)类表达式将在TS中出现,这将允许它们在IIFE中使用。此外,这段关于TypeScript中模块模式的视频(我制作)可能对您有用:@AluanHaddad-是的,现在可以了。这在2014年12月是不允许的。嗨,谢谢回复。我正在编辑我的问题,以便在我的行中展开“如果我将类放在TypeScript模块中,那么js将以模块名称作为全局变量生成:”-编辑是生成的代码,与您的代码几乎相同。关键是(在您的示例中)var MyModule现在是全局的。我们已将控制器全局替换为模块全局。如果另一个javascript库有一个MyModule全局变量,那么混乱就会接踵而至@user603563-不完全是因为它使用的是显示模块模式。因此,如果模块已经存在,它不会重新定义该模块。只有当你在模块中添加了一些你期望外部可用的东西时,混乱才会随之而来。在这种情况下,您没有将类添加到模块中,因此不会发生冲突。这只是一个简单的过程。我刚刚回到我的JS引用,是的,我再次了解到,与使用核函数来创建以前声明的MyObject不同,MyObject的后续变量只会添加到现有对象中(或者,如果像本例一样,没有对MyObject进行任何操作,则不会更改)。好的(尽管我很讨厌,因为它不能回答TypeScript是否可以完全避免污染全局范围)我会将此标记为答案,因为有了这些注释,这确实充分解释了为什么它没有我想象的那么重要…@AluanHaddad-我理解,但问题是专门关于使用TypeScript语法的。在撰写本文时,规范的做法是创建一个不带导出的
模块
,这是正确的创建了一个闭包。从那时起,情况发生了很大变化,内部模块是使用
名称空间
创建的。从长远来看,我可能会认为使用real
es6
模块是一个更好的选择。@Josh yes es6模块更可取。不管问题是如何做到这一点而不污染名称空间。名称空间只是内部模块的一个新关键字。问题的关键是,对于所问的问题,有一个非常简单的答案,而不是您给出的答案,事实上,没有人给出
(function () {
  class MyController {
    static $inject = ['$scope'];
    contructor($scope: ng.IScope & { myNewProperty: string }) {
      $scope.myNewProperty = 'Bob';
    }
  }

  angular.module('myModule', [])
    .controller('MyController', MyController);
})();