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.

Relaterte artikler