現在我努力完成這項工作:完全封裝並且不需要實例化「新」的完美課程。搜索過了一會兒,我想出了這個:
function Test(x){
var innerFunction = function(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new innerFunction(x);
}
但測試結果證明是錯誤的:
var a = Test("foo");
var b = Test("baz");
alert(a.constructor == b.constructor); //false, not good!
alert(a.constructor.name == b.constructor.name); //true
所以似乎有錯誤的範圍,所以我用一個公開內部函數 :
function Test(x){
function innerFunction(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new innerFunction(x);
}
並運行一些廣泛的測試,證明它是正確的:
var a = Test("foo");
var b = Test("baz");
alert(a.constructor == b.constructor); //true, made it!
alert(a.constructor.name == b.constructor.name); //true
alert(a.getA()); //"foo" as expected
alert(a.getA() == b.getA()); //false as expected
a.variable = "whatever";
alert(a.getA()); //"foo" as expected
alert(a.variable); //"whatever", doesn't seem preventable
a.setA("somewhere");
alert(a.getA()); //"somewhere", as expected
alert(a.variable); //"whatever", doesn't seem preventable
但是,我們可以用這種方式使用幾個函數嗎?這是我的第一種方法:
function Test(x){
function innerFunction(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new innerFunction(x);
}
function TestToo(x){
function innerFunction(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new innerFunction(x);
}
var a = Test("foo");
var b = Test("baz");
var c = TestToo("foo");
var d = TestToo("baz");
alert(a.constructor == b.constructor); //true, as expected
alert(a.constructor.name == b.constructor.name); //true, as expected
alert(c.constructor == d.constructor); //true, as expected
alert(c.constructor.name == d.constructor.name); //true, as expected
alert(a.constructor == c.constructor); //false, as expected
alert(a.constructor.name == c.constructor.name); //true, as NOT expected
這就是它嗎?我們是否真的總是需要知道使用字符串來比較a.constructor.name
的內部類結構?真是沒有,因爲在Javascript中你可以從字面上做的一切(你只需要知道如何,不爲什麼),我發現這個最終的解決方案:
function Test(x){
function Test(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new Test(x);
}
function TestToo(x){
function TestToo(y){
var variable = y;
this.getA = function(){
return variable;
}
this.setA = function(x){
variable = x;
}
}
return new TestToo(x);
}
var a = Test("foo");
var b = Test("baz");
var c = TestToo("foo");
var d = TestToo("baz");
alert(a.constructor == b.constructor); //true, as expected
alert(a.constructor.name == b.constructor.name); //true, as expected
alert(c.constructor == d.constructor); //true, as expected
alert(c.constructor.name == d.constructor.name); //true, as expected
alert(a.constructor == c.constructor); //false, as expected
alert(a.constructor.name == c.constructor.name); //false, q.e.d.!
我是認真的,我不知道爲什麼會這樣作品。但它肯定有效,100%對象封裝,與Java類1:1相等。 ;-)
爲什麼你忘記關鍵字new?我的意思是,每次創建一個新對象時,都使用「新」,這非常簡單。這個解決方案在許多OO語言中存在了幾十年,這是一件好事,因爲每個人都可以閱讀和理解你的代碼。雖然沒有人理解var obj = Test('string'),但你的代碼可讀性較差。但我知道,這是一些JS程序員的最終目標。 ;) – Marcus
@Marcus,如上所述,'new'關鍵字不是這種模式的唯一優勢。另外,我不是團隊中唯一的程序員。假設每個人都會記得使用'new'關鍵字,同時在Python中編寫後端(它不會爲類使用'new')是不現實的。在類聲明結束時發現丟失的'new'要比創建每個實例更容易。 –
啊,我現在明白了:沒有編譯器告訴程序員他忘記了「新」,所以這就是爲什麼你不想使用它。 – Marcus