2016-03-25 19 views
7

Patrząc na ten kod maszynopis:Dlaczego TypeScript generuje IIFE dla klasy?

class Greeter { 
    greet() {} 
} 

Generuje Iife (Natychmiast-Wykonano wyrażenie funkcyjne) wokół funkcji konstruktora i wszystkie deklaracje funkcji prototyp jak:

var Greeter = (function() { 
    function Greeter() { 
    } 
    Greeter.prototype.greet = function() { }; 
    return Greeter; 
}()); 

Co jest zaletą? Kiedy czytam o IIFE, widzę wiele zastosowań w definiowaniu modułów. O ile widzę, maszynopis nie generuje niczego wewnątrz IIFE, które zanieczyszczałoby globalną przestrzeń nazw.

Moim zdaniem nie ma przewagę nad tym deklaracji klasy:

var Greeter = function() {} 
Greeter.prototype.greet = function() { }; 

Jaki jest powód?

+0

Prawdopodobnie uproszczenie kodu maszynopis, tak że nie trzeba zgadywać, kiedy potrzebuje Iife czy nie, to jest zaleta. To naprawdę nie ma znaczenia, prawda? Jeśli byłby to napisany ręcznie kod, miałbyś więcej punktów. –

+1

Dla facetów, którzy głosowali, aby zamknąć to pytanie: To nie jest oparte na opiniach. Kompilator TS robi to w ten sposób, a pytanie brzmi: dlaczego. Zakładam, że jest przynajmniej jedna przyczyna tej decyzji. – Tarion

Odpowiedz

6

To jest interesujące. Myślę, że kompilator maszynowy kompiluje ClassDeclaration wydedukowany z ClassExpression s, przez przypisanie wyrażenia do zmiennej w zakresie, więc nie muszą one obsługiwać tych przypadków niezależnie. Upraszcza to kompilator TypeScript i sprawia, że ​​wygenerowany kod jest nieco modułowy (powiedziałbym, że jest bardziej czytelny, ale to tylko kwestia gustu).

class Bar { }; 
foo(class Baz { }); 
var Baa = class Bab { }; 

Sporządza się:

var Bar = (function() { 
    function Bar() { 
    } 
    return Bar; 
}()); 
; 
foo((function() { 
    function Baz() { 
    } 
    return Baz; 
}())); 
var Baa = (function() { 
    function Bab() { 
    } 
    return Bab; 
}()); 

widać, ClassDeclaration jest kompilowany jako ClassExpression przypisany do zmiennej lokalnej.

9

Aby uniknąć zanieczyszczenia globalnej przestrzeni nazw.

Jest to wzorzec klęski, w którym funkcje wewnętrzne mają dostęp do właściwości ich rodziców. Wg IIFE, ODNOŚNIK do funkcji wewnętrznych zwróconych.

Poniżej są dwa scenariusze, w których Iife wzór jest bardzo pomocne i powód, dlaczego maszynopis kompilator generuje Iife wzoru: Realizacja

  1. Dziedziczenie: gdzie przechodzi BaseClass jako argument Iife. Gdyby nie było IIFEE, to BaseClass byłaby zmienną globalną, a więc zanieczyszczającą globalną przestrzeń nazw.

maszynopis:

class Greeter extends BaseController { 
    greeting: string; 
    constructor(message: string) { 
     this.greeting = message; 
    } 
    greet() { 
     return "Hello, " + this.greeting; 
    } 
} 

JS:

var Greeter = (function(_super) { 
    __extends(Greeter, _super); 

    function Greeter(message) { 
     this.greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + this.greeting; 
    }; 
    return Greeter; 
}(BaseController)); 
  1. Moduł wdrożenie wzoru: gdzie aplikacja ma tylko jedną zmienną globalną jak ' "i wszystkie inne funkcje są pakowane w obiekty takie jak app.cart, app.catalog itd. Tam tylko zmienna jest wyeksponowana przez moduły, a wszystkie inne funkcje są dodawane do samych modułów, co jest możliwe tylko przez IIFE.

maszynopis:

module App.Controller { 
    export class Greeter extends BaseController { 
     greeting: string; 
     constructor(message: string) { 
      this.greeting = message; 
     } 
     greet() { 
      return "Hello, " + this.greeting; 
     } 
    } 
} 

JS:

var App; 
(function (App) { 
    var Controller; 
    (function (Controller) { 
     var Greeter = (function (_super) { 
      __extends(Greeter, _super); 
      function Greeter(message) { 
       this.greeting = message; 
      } 
      Greeter.prototype.greet = function() { 
       return "Hello, " + this.greeting; 
      }; 
      return Greeter; 
     }(BaseController)); 
     Controller.Greeter = Greeter; 
    })(Controller = App.Controller || (App.Controller = {})); 
})(App || (App = {})); 

Kopiuj/Wklej ten kod do konsoli js przeglądarek i jedyną zmienną App zostanie utworzony w skali globalnej. Funkcja odpoczynku będzie dostępna w aplikacji.

Dzięki, mkdudeja

+1

OP stwierdził, że kod nie zanieczyszcza globalnej przestrzeni nazw, i nie widzę, jak by to zanieczyszczało globalną przestrzeń nazw. Czy mógłbyś wyjaśnić? –

+0

Tylko dlatego, że odwołanie do funkcji wewnętrznej jest natychmiast przypisywane do zmiennej o tej samej nazwie –

+0

Jeśli masz rację, znajdź przykład, który spowodowałby zanieczyszczenie globalnej przestrzeni nazw. Wszystkie deklaracje zmiennych klasy zdarzają się na prototypie. Przeczytałem dokumentację klasy maszynopisów i niczego nie znalazłem. – Tarion

Powiązane problemy