javascript - TypeScript - hun må ha det? (hvor det == globalt område)
Jeg konverterer en Angular-app til å bruke TypeScript, men dette er et generelt TypeScript-spørsmål, ikke om Angular. Angular JS-filene er omtrent som følgende:
(function () {
var app = angular.module('myModule', []);
app.controller('myController', ['$scope',
function ($scope) {
$scope.myNewProperty = "Bob";
}
]);
})();
Og jeg har konvertert det til nydelig TypeScript-klasseskinn:
class myController {
constructor($scope) {
$scope.myNewProperty = "Bob";
}
}
angular.module('myModule', []).controller("myController", myController);
Alt fungerer fint, bortsett fra at den genererte JS-en ikke er pakket inn i henhold til JS-modulmønsteret (dvs. i en ytre anonym funksjon):
var myController = (function () {
app.controller('myController', ['$scope',
function ($scope) {
$scope.myNewProperty = "Bob";
}
]);
})();
var app = angular.module('myModule', []);
Så myController er nå global. Hvis jeg legger klassen i en TypeScript-modul, genereres js med modulnavnet som en global variabel:
var TsModule;
(function (TsModule) {
var myController = (function () {
app.controller('myController', ['$scope',
function ($scope) {
$scope.myNewProperty = "Bob";
}
]);
})();
var app = angular.module('myModule', []);
})(TsModule || (TsModule = {}));
Hvordan kan jeg stoppe TypeScript fra å forurense det globale navnerommet på denne måten? Jeg vil bare at alt skal være pakket inn i et fint lokalt område. Jeg har sett det bli sagt andre steder "bare gå tilbake til den gamle JS-syntaksen" (dvs. ingen TypeScript-klasse). Hvordan kan jeg definere en AngularJS-tjeneste ved hjelp av en TypeScript-klasse som ikke forurenser det globale navnerommet?
Men hele poenget med at vi bruker TypeScript /er/ klassesyntaksen. Er TypeScript i strid med noen (fornuftige) JS-programmerere som vet at man ikke skal gå globalt?
Svar #1
Du kan enkelt omslutte klassen din inne i en module
Selve modulen vil være global, men hvis du ikke eksporterer klassen, er det liten risiko for å forurense det globale området med ett modulnavn.
Så denne TypeScript:
module MyModule {
class MyClass {
constructor(){}
}
}
Vil produsere følgende JS:
var MyModule;
(function (MyModule) {
var MyClass = (function () {
function MyClass() {
}
return MyClass;
})();
})(MyModule || (MyModule = {}));
Svar #2
Rask oppdatering
I de nyeste versjonene av TypeScript kan du nest en klasse inne i en IIFE:
(() => {
class Example {
}
})();
Det resulterende resultatet er:
(function () {
var Example = (function () {
function Example() {
}
return Example;
}());
})();
Originalt svar
Du kan unngå å legge til i det globale omfanget ved å bruke et modulmønster som AMD eller CommonJS. Når du bruker en av disse, blir hver TypeScript-fil betraktet som en ekstern modul og holdt utenfor det globale omfanget.
Dette eksempelet fjerner Angular for eksempelets formål, men mens RequireJS legger til define-metoden i global, plasseres ingen av kodene dine i dette området.
MinModul.ts
export class myController {
constructor($scope) {
$scope.myNewProperty = "Bob";
}
}
app.ts
import MyModule = require('MyModule');
var controller = new MyModule.myController('');
HTML
<script src="Scripts/require.js" data-main="app.js"></script>
Hvordan app.js ser ut:
define(["require", "exports", 'MyModule'], function (require, exports, MyModule) {
var controller = new MyModule.myController('');
});
Alternativt... som du vet... kan du fortsatt implementere alt ved å bruke JavaScript du allerede bruker hvis du ønsker - du vil fortsatt få autofullføring og typkontroll, som er store fordeler selv om du ikke får klasser.
