2012-10-02 82 views
17

我正在閱讀有關Microsoft提供的新類似JavaScript的語言TypeScript。在playground (example section)中,TypeScript語法中有一個簡單類轉換爲JavaScript代碼。從Java編程背景來看,學習從TypeScript編譯的JavaScript如何完成OOP是有趣的。爲什麼在匿名函數()調用中嵌入JavaScript類?

打字稿代碼:

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

var greeter = new Greeter("world"); 

var button = document.createElement('button') 
button.innerText = "Say Hello" 
button.onclick = function() { 
    alert(greeter.greet()) 
} 

document.body.appendChild(button) 

以及等效的JavaScript代碼:

var Greeter = (function() { 
    function Greeter(message) { 
     this.greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + this.greeting; 
    }; 
    return Greeter; 
})(); 
var greeter = new Greeter("world"); 
var button = document.createElement('button'); 
button.innerText = "Say Hello"; 
button.onclick = function() { 
    alert(greeter.greet()); 
}; 
document.body.appendChild(button); 

打字稿部分非常類似於Java,所以我理解這一點。現在我的問題是爲什麼在JavaScript中,Greeter類的主體嵌入在匿名function()調用中?

爲什麼不把它寫成這樣?

function Greeter(message) { 
    this.greeting = message; 
} 
Greeter.prototype.greet = function() { 
    return "Hello, " + this.greeting; 
}; 

每種方法的優點/缺點是什麼?

+0

JavaScript代碼沒有特別使用立即調用的匿名函數。你是對的,它可以被刪除。 –

+1

我認爲這將是'私人'成員,但是......添加'私人'不會改變任何東西。 – 2012-10-02 14:32:56

回答

13

以下稱爲立即調用函數表達式

(function(){ ... })(); 

它是用來保持全球範圍內的清潔。儘管如此,由於返回值被分配給變量Greeter,所以這不是必需的。這種模式唯一有用的是當你想要「私人」靜態成員。

例如爲:

var Greeter = (function() { 
    var foo = 'foo', bar = 'bar'; /* only accessible from function's defined 
            in the local scope ... */ 

    function Greeter(message) { 
     this.greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + this.greeting; 
    }; 
    return Greeter; 
})(); 
+0

在這種情況下'foo'和'bar'將是私有的並且是靜態的。 –

2

匿名功能/自執行閉合通常用於封裝範圍,以便僅返回的值是它的可訪問的外部。 (或任何你附加到其他對象,如窗口)

1

匿名函數可能是爲了防止名稱與代碼的其他部分相互作用。可以這樣想,在你的匿名函數中,你甚至可以聲明一個名爲「$」的變量作爲你想要的任何東西,同時在你的代碼的其他部分使用jQuery而不會發生衝突。

+1

它分配到相同的名稱,但。 – 2012-10-02 14:31:53

+0

我不明白你的意思....你能詳細說一下評論嗎? – Deleteman

2

這是爲了允許私人會員。在這個例子中,所有成員都是公共的,所以你的兩個結構是等價的。但是,如果您想爲私人成員提供服務,則需要通過封閉將其從調用範圍中隱藏起來。因此,如果你有一個私有成員,像這樣:

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

你可能會得到這樣的事情:

var Greeter = (function() { 
    var greeting=""; 
    function Greeter(message) { 
     greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + greeting; 
    }; 
    return Greeter; 
})(); 

問候變量將提供給匿名函數中定義的所有功能,但看不見無處不在其他。

+1

不,它不。 'var greeting'沒有被創建,它只在內部使用。我只是試過;) – PiTheNumber

+0

你會認爲你會得到這樣的東西,但你不會。 TypeScript只在編譯時執行'private'修飾符,所以即使在使用它時,它仍然會設置'this.greeting'(顯然它根本不是私有的 - 但是如果你試圖訪問它,你的TypeScript將不會編譯)。 –

+0

啊然後我會猜測,有一些隱藏的屬性,由框架產生,不應該污染產生的對象,只是不是私人成員 –

3

除了明顯的範圍/關閉推理。使用立即調用的匿名函數可以預加載(解釋)類定義。這允許任何JIT優化在執行中被前置加載。簡而言之,對於更復雜的應用程序,它會提高性能。

+4

您可以鏈接到具有關於JIT部件的更多信息的源文件嗎? – Ciddan

-4

關閉是唯一的均值來調用構造函數與參數:

var w = new Greeter("hello") 

還有其他方法,但是所有的複雜,有侷限性和缺點。

相關問題