首先,我要解決這個位:
...我怎麼能像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)會創建一個單獨的執行上下文,其中的所有函數都將關閉。這意味着即使在函數返回之後,他們仍可以實時訪問在該上下文中定義的變量和函數。由於您只調用一次,因此只有一個上下文,因此只有一個myVariable1
和myMethod3
。
在我的例子創建私有例如信息,我們使用的是一個新的上下文爲創建的每個呼叫給構造函數的事實。該上下文不與其他任何內容共享,因此變爲特定於實例。
有一種方式來獲得附近 - 私人實例屬性,而無需在構造函數中,這是使用一個隨機選擇的名稱來定義功能:
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的詳細信息。
'我如何將我的傳統知識,類型化的面向對象的語言,如Java,應用到JavaScript'你不能像JavaScript那樣安靜。它需要不同的思維方式。 JS中沒有「類」的東西(即使ES2015假裝存在),被稱爲「類」的是可調用的動態對象(構造函數),可以在所有實例之間共享屬性和方法。一旦對象的原型發生變化,所有實例都將受到影響。 –