2012-01-01 24 views
3

我正在尋找最優化的方式來在JS中有一個對象;因爲JS允許你以多種方式做某件事,我想知道哪些被認爲是「最佳實踐」。最優化的方式來創建JS對象

的概念使用的對象將是這樣:

var John = new Person('John'); 
var Foo = new Person('Foo'); 

console.log(John.getName()); //Return 'John' 
console.log(Foo.getName()); //Return 'Foo' 
console.log(John.name); //undefined 
console.log(Foo.name); //undefined 

我有一些例子這裏:

示例#1:

var Person = function (name) { 
    this.getName = function() { return name; } 
} 

在這裏,我實際上沒有性能; 「name」不能被改變或被public讀取,並且getName方法可以被公開訪問並且使用本地名字變量來調用。這實際上符合我的需求。

例子#2:

function Person (name) { 
    this.getName = function() { return name; } 
} 

這具有相同的行爲與實施例1#。從功能和性能角度來看,我只是不確定var method = function() {};function method() {};之間的區別。

實例#3:

var Person = function (name) { 
    this.name = name;  
    Person.prototype.getName = function() { return this.name; } 
} 

這裏我有名稱屬性可以由公衆所讀/寫和我也有可訪問公衆的原型的getName方法。

示例4:

var Person = function (name) { 
    this.name = name; 
    if (!Person._prototyped) { 
     Person.prototype.getName = function() { return this.name; } 
     Person._prototyped = true; 
    } 
} 

這裏我有什麼,我曾在例如#3,我要確保在需要時原型方法只設置一次,只是有一點不同。

所以最終的問題是,你會建議我遵循哪些人,或者如果他們中的任何一個那麼最好的做法是哪一種?

+0

儘管沒有公共*名稱*屬性,* getName *是公共的,並且可以被有效替換* name *可以被修改。上述提供的公共*名稱*屬性沒有任何好處,它只是使用更多的資源用於閉包和額外的函數調用來訪問該值。儘管使用getter有正當理由。 – RobG 2012-01-01 07:00:41

回答

3

你想要的東西,最好的辦法大概是這樣的:

/** 
* @constructor 
*/ 
function Person(name) { 
    this.getName = function() { 
     return name; 
    }; 
} 

這是爲什麼?那麼,首先,封裝。如果可能的話,你一般都希望把函數原型,像這樣:

/** 
* @constructor 
*/ 
function Person(name) { 
    this.name = name; 
} 

Person.prototype.getName = function() { 
    return this.name; 
}; 

但是!在這種情況下,您不希望Person.name可以訪問。出於這個原因,你需要使用閉包。

至於這個方法:

var Person = function (name) { 
    this.name = name;  
    Person.prototype.getName = function() { return this.name; } 
} 

這不是很好。您公開公開this.name,因此它與以前的原型方法相比沒有任何優勢,但您會不斷用相同的函數覆蓋Person.prototype.getName。這樣做沒有意義; this將是每次適當的對象。更重要的是,Person.prototype.getName將不會被訪問,直到第一個Person對象被實例化,所以沒有太多的使它「公開」的位置。你的第四個例子基本上是相同的,更多的問題使它更難理解,但它仍然具有所有的缺點。

所以,在這種情況下,去第一個版本;但如果可能,請在prototype上設置方法,以便可以在實例外調用它們。

最後,我建議使用:

function Person() { 
} 

var Person = function() { 
} 

,因爲1)第二個例子缺少分號,2)var意味着構造是可變的,它應該不是,3)我不相信JDoc允許@constructor被應用於它,在Closure Compiler中至少導致一個警告。


好了,就不那麼重要了。但仍然...

+0

你好,謝謝你的回覆!:)只是一個問題,如果我們說我不在乎財產是否可以公開訪問,那麼您更喜歡哪種方式,爲什麼?可能通過對性能問題進行原型設計的原型正確嗎? – panosru 2012-01-01 04:02:40

+1

@panosru:可能通過原型方法。這可能會更高效,但重要的是您可以執行諸如「Person.prototype.getName.call(someObj)'之類的操作。 – Ryan 2012-01-01 04:24:03

+1

和你喜歡的那兩個之間,爲什麼? #1 'function Person(name){ this.getName = function(){return name; } }' #2 'function Person(name){ return { getName:function(){return name; } } }' – panosru 2012-01-01 04:29:02

2

在示例3和4應該是:

var Person = function (name) { 
    this.name = name;  
}; 
Person.prototype.getName = function() { return this.name; } 

和:

var Person = function (name) { 
    this.name = name; 
}; 

if (!Person._prototyped) { 
    Person.prototype.getName = function() { return this.name; } 
    Person._prototyped = true; 
} 

當你不需要與原型爛攤子每次調用構造函數時。

不知道哪個是最快的(因爲它們都適用於您的目的),這是您的要求,但我不會擔心,因爲這看起來像是微型優化。如果你一定要知道,那麼你可以使用這樣的網站http://jsperf.com/

我能想象的最快方法是:

function Person(name) { 
    this.getName = function() { 
     return name; 
    }; 
} 

正如MiniTech移動說。原因如下:

每次js引擎都要「向上」的原型鏈,它會帶走一小部分毫秒(或IE的一小部分秒:)),並聲明變量可以採取(也可以忽略不計),你也避免這樣做。希望幫助

+0

對於示例#3是的,我同意你的看法,但爲什麼對於示例#4?因爲放置了一個標誌,所以原型實際上不會被設置多次,只有在需要時纔會設置。 – panosru 2012-01-01 03:49:37

+0

@panosru:因爲檢查('if')也佔用一些計算能力和時間。 – qwertymk 2012-01-01 03:51:57

+0

當然是,但旁邊沒有任何「問題」,我的意思是使用這種方式是正確的?我其實從來沒有使用它我只是在這裏看到它:http://stackoverflow.com/a/546717/395187這就是爲什麼我問:) – panosru 2012-01-01 03:57:56

0

在node.js上正常工作。 AFAIK,參數是可變的。閉包會記住價值。因此,這將起作用。我想這解決了這一切。

var Person = function(Name) { 
    this.getName = function(){return Name;} 
    this.setName = function(newName) { Name = newName; } 
}, 

me = new Person('John'); 
console.log(me.getName()); 
me.setName('Peter'); 
console.log(me.getName());