2015-12-25 38 views
-2

是否可以使用如下所示的語句來定義不使用prototype的方法?定義不使用原型的方法

Person.sayHello = function() {...} 

在這個例子中

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

Person.prototype.sayHello = function() { 
    console.log("Hello, I'm " + this.firstName); 
}; 

var person1 = new Person("Alice"); 
var person2 = new Person("Bob"); 
+0

這不是語言的工作原理。你爲什麼想要或需要這樣做? – meagar

+0

只是想知道這兩個^ _^ –

+0

我不知道的區別。當你嘗試它時它有效嗎? –

回答

4

總之,沒有。

Person.sayHello = function() {...}; 

該行將向Person類本身添加一個名爲「sayHello」的函數,而不是Person類的實例。因此,它只能通過

Person.sayHello(); 

,而不是如果你熟悉Java或C#援引

var matt = new Person('Matt'); 
matt.sayHello(); 
// sayHello is not defined on matt 

,加上以這種方式的人的方法是像創建一個靜態方法。

然而,我們可以添加一個方法的實例,而無需向原型添加方法。

方法1:在人這種方法的

var Person = function (firstName) { 
    this.firstName = firstName; 

    this.sayHello = sayHello() {...}; 
}; 

構造函數創建「的sayHello」功能有一個新功能是用於人的每一個實例創建的缺點。也就是,

var frank = new Person('Frank'); 
var matt = new Person('Matt'); 
// frank.sayHello != matt.sayHello; 

因此,這種方法可能在內存上很難。但是,它確實允許通過關閉進行封裝(例如,私有狀態)。在下面的示例中,不調用「sayHello」函數就不能修改Person類之外的「count」變量。

var Person = function (firstName) { 
    this.firstName = firstName; 

    this.sayHello = sayHello() { 
    count++; 
    console.log("Hello has been said " + count + "times". 
    }; 

    var count = 0; 
}; 

方法2:人的構造以外創建「的sayHello」功能和Person

var Person = function (firstName) { 
    this.firstName = firstName; 

    this.sayHello = sayHello; 
}; 

function sayHello() {...} 

此方法的構造內分配給它具有較低的內存使用情況的優點; sayHello函數只有一個實例,它在Person的實例間共享。即,

var frank = new Person('Frank'); 
var matt = new Person('Matt'); 
// frank.sayHello == matt.sayHello; 

這使得它與原型方法相似。然而,函數的賦值給每個實例仍然比原型方法消耗更多的內存,其中函數只被賦值給原型對象。

但是,與原型方法一樣,此方法不允許使用私有狀態。所有狀態必須通過this關鍵字通過公開狀態進行訪問。


更新:在存儲器使用方法1和方法2之間

方法1的差的澄清是這樣的:

var function1 = function() { console.log('Hello'); }; 
var function2 = function() { console.log('Hello'); }; 

的函數具有相同的特性,但不平等。 JavaScript不知道它們在功能上是相似的,所以它在內存中創建兩個函數來表示它們。

方法2是這樣的:

var sayHello = function() { console.log('Hello'); }; 
var function1 = sayHello; 
var function2 = sayHello; 

現在功能1和功能2實際上是相同的功能,因爲它們都只是堅持sayHello的參考。


更新:模塊模式的實施例的使用,以避免在方法2

該模塊定義由匿名閉合限定的模塊中的Person類加入「的sayHello」到全球範圍內(一個自我執行的函數)並將其導出到全局範圍。由於「sayHello」在模塊的關閉中定義,並且未導出,因此不會將其添加到全局範圍。

var Person = (function() { 
    function Person(firstName) { 
     this.firstName = firstName; 

     this.sayHello = sayHello; 
    }; 

    function sayHello() {...} 

    return Person; 
}()); 
+0

在理解以下方面存在一些困難:只有一個sayHello函數實例,它在Person實例間共享。我認爲這是沒有什麼不同,除了方法二沒有訪問私有變量 –

+0

所以方法1是這樣的: var function1 = function(){console.log('Hello'); }; var function2 = function(){console.log('Hello'); }; 這些函數具有相同的行爲,但不相等。 JavaScript不知道它們在功能上是相似的,所以它在內存中創建兩個函數來表示它們。 方法2是這樣的: var sayHello = function(){console.log('Hello'); }; var function1 = sayHello; var function2 = sayHello; 功能1和功能2現在是相同的功能,因爲它們都只是簡單地保持對sayHello的引用。 – MattTannahill

+0

對不起,你的意思是? –

-3

當然可以,但SayHello的功能將無法訪問任何對象屬性(即this.myvar),你只能把它像一個靜態方法:

Person.sayhello()  

(而不是mypersonobject.sayhello)。

當您擴展原型時,sayhello函數可用於通常使用'new'關鍵字創建的所有Person對象。

https://jsfiddle.net/jsheridan390/kL7arrqs/

+0

但我添加sayHello函數的人,而不是特定的對象,新創建的對象應該繼承人定義的函數。我在哪裏丟失?謝謝 –

+0

您可以將屬性分配給函數變量,但這並不意味着它們將在構造對象中可用。據我所知,當你使用'new Person()'創建一個新對象時,只有原型函數被複制。 – jsdeveloper

+0

所以,當我們使用像下面這樣的知道它的意義時:Person.sayHello = ...?謝謝 –

-1

這將是不可思議的,但如果你真的需要做這樣的說法,你可以一次功能分配給自己的原型,那麼所有的功能添加到主函數。

var Person = function (firstName) { 
    this.firstName = firstName; 
}; 
Person.prototype = Person; 

Person.sayHello = function() { 
    console.log("Hello, I'm " + this.firstName); 
}; 
0

是的,你可以。如果您來自傳統的面向對象背景,可能有助於將此視爲有效地表現爲類的公共靜態屬性。

由於jsdeveloper在上述評論中說過。函數只是可以執行的對象。您可以像添加任何其他對象一樣爲它們添加屬性。這種技術實際上用於記憶或咖喱等模式。

在你的情況下,sayHello可以訪問任何可以訪問Person功能的地方。它與繼承/原型沒有什麼關係,因爲它不需要通過遍歷原型鏈來解決屬性問題,但它是使數據可訪問的另一種方法。

我敢肯定它的基礎上開發不同,但我經常把純函數不引用this爲靜態方法爲你做了,因爲它們更容易測試,使意圖明顯給其他開發者

相關問題