2016-07-07 205 views
3

我想了解「類」是如何在ES5中工作的,以及如何將我的傳統知識,如Java類型的面嚮對象語言應用於JavaScript。javascript中的類和訪問修飾符

在下面的代碼示例中,我評論了我的問題。

var MyClass = (function() { 

    // [What am I?] A private variable? 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

我主要想知道「私人」的東西。就像,如果我有這個類的多個實例會發生什麼?他們可以互相干涉私人變量和功能嗎?

+1

'我如何將我的傳統知識,類型化的面向對象的語言,如Java,應用到JavaScript'你不能像JavaScript那樣安靜。它需要不同的思維方式。 JS中沒有「類」的東西(即使ES2015假裝存在),被稱爲「類」的是可調用的動態對象(構造函數),可以在所有實例之間共享屬性和方法。一旦對象的原型發生變化,所有實例都將受到影響。 –

回答

4

首先,我要解決這個位:

...我怎麼能像Java應用我的傳統,類型化的面嚮對象語言的知識的JavaScript。

你可以經常逃脫的JavaScript的思維是一個有點像Java/C#/等,但如果這樣做,A),它會在某個時候咬你,因爲JavaScript是像Java/C#/等,它基本上是不同,即使它有一些使它看起來相似的圖案;和B)由於不知道如何使用它的根本不同的性質,你會錯過JavaScript的真正力量。 (我怎麼知道?我沒有正是,從一個Java [甚至C++]背景來了,假設JavaScript的是相似的。)

那不是遠程意味着作爲任何形式的批評,它只是給一個字明智的。嘗試深入學習JavaScript原型繼承和閉包的工作方式,並且您會發現解決問題的方式與您在Java/C#/等中的方式稍有不同。

答案內聯:

var MyClass = (function() { 

    // [What am I?] A private variable? 
    // ==> A private *class* variable (static variable). Not instance-specific. 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     // ==> A public field/property/variable, choose your terminology. :-) 
     // ==> The Java spec calls them both fields and variables (oddly). 
     // ==> In JavaScript, they're called properties. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    // ==> Correct, but note that myVariable1 is shared across all instances 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    // ==> Yes, note that this one is returning an instance-specific field/property/variable 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    // ==> A private *class* method (static method), yes. 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

我最好奇的 「私人」 的東西。就像,如果我有這個類的多個實例會發生什麼?他們可以互相干涉私人變量和功能嗎?

是的,正如我在評論中提到的,他們是全班同學。如果你想有一個私人「例如場」,你有你的構造函數中聲明它,並創建需要有在構造函數中對它的訪問,讓他們關閉了它所有的功能:

function MyClass(arg) { 
    var privateInstanceInfo = arg; // We could also just use arg directly 

    this.accessThePrivateInstanceInfo = function() { 
     return privateInstanceInfo * 42; 
    }; 
} 
MyClass.prototype.useOnlyPublicInfo = function() { 
    // This cannot access `privateInstanceInfo` directly. 
    // It *can* access the function `accessThePrivateInstanceInfo` 
    // because that's public: 
    return accessThePrivateInstanceInfo(); 
}; 
var c = new MyClass(2); 
console.log(c.useOnlyPublicInfo()); // 84 

這都源於一個名爲關閉概念,對此進行了詳細的這個問題,它的答案概述:How do JavaScript closures work?我還要從幾年前Closures are not complicated參考我的文章,而它使用的東西一些舊條款與最新規範相比,仍然很好地描述了這些概念。

您用作包裝的內聯調用函數(IIFE)會創建一個單獨的執行上下文,其中的所有函數都將關閉。這意味着即使在函數返回之後,他們仍可以實時訪問在該上下文中定義的變量和函數。由於您只調用一次,因此只有一個上下文,因此只有一個myVariable1myMethod3

在我的例子創建私有例如信息,我們使用的是一個新的上下文爲創建的每個呼叫給構造函數的事實。該上下文不與其他任何內容共享,因此變爲特定於實例。

有一種方式來獲得附近 - 私人實例屬性,而無需在構造函數中,這是使用一個隨機選擇的名稱來定義功能:

function makeRandomName() { 
    var str = ""; 
    while (str.length < 10) { 
     str += String.fromCharCode(32 + Math.floor(95 * Math.random())); 
    } 
    return "__" + str; 
} 
var MyClass = (function() { 
    var pseudoPrivatePropName = makeRandomName(); 

    function MyClass() { 
     this[pseudoPrivatePropName] = 42; 
    } 

    // .... 

    return MyClass; 
})(); 

的IIFE中的代碼知道名字的財產,其外的代碼沒有。現在,惡意代碼仍然可以找到該屬性,但它變得更具挑戰性,特別是如果您擁有多個惡意代碼。 (如果你有一個以上的,你需要一個更好的名字分配器比上面一個)。

在ES2015(ES6),你可以使用

var pseudoPrivatePropName = Symbol(); 

...而不是有一個名字分配器。

在我的博客this somewhat-outdated article的詳細信息。

+1

非常感謝您的精心解答! – datcat