簡體   English   中英

關於JavaScript如何工作的一些問題

[英]A few questions about how JavaScript works

我最近一直在深入研究JavaScript以完全理解語言,並且有一些嘮叨的問題,我似乎無法找到答案(特別是處理面向對象的編程)。

假設以下代碼:

function TestObject()
{
    this.fA = function()
    {
        // do stuff
    }

    this.fB = testB;

    function testB()
    {
        // do stuff
    }
}

TestObject.prototype = {
    fC : function 
    {
        // do stuff
    }
}

函數fAfB什么區別? 他們的范圍和潛在能力是否完全相同? 它只是慣例還是技術上更好或更合適的一種方式?

如果在任何給定時間只有一個對象的實例,那么將原型中的函數添加到fC是否值得? 這樣做有什么好處嗎? 原型只在處理對象或繼承的許多實例時才真正有用嗎?

從技術上來說,每次都按照我上面的方式或者調用TestObject.prototype.functionName = function(){}方法向原型添加方法的“正確”方法是什么?

我希望盡可能保持我的JavaScript代碼干凈和可讀,但我也非常感興趣的是對象的正確約定在語言中。 我來自Java和PHP背景,我試圖不對JavaScript如何工作做任何假設,因為我知道它是基於原型的非常不同。

函數fA和fB之間有什么區別

在實踐中,沒有。 函數表達式(fA)和函數聲明(fB)之間的主要區別在於創建函數時(聲明的函數在執行任何代碼之前可用,而函數表達式在表達式實際執行之前不可用)。 您可能會偶然發現與函數表達式相關的各種怪癖。

在這個例子中,我使用函數表達式,只是因為聲明一個函數表達式,然后分配結果似乎有點抽象。 但這兩種方法都沒有“正確”或“錯誤”。

如果在任何給定時間只有一個對象的實例,那么將原型中的函數添加到fC中是否值得?

沒有。幾乎所有進行繼承的人都發現普通對象通常更簡單,因此“更好”。 原型繼承對於修補內置對象非常方便(例如,在缺少的情況下添加Array.prototype.each)。

從技術上講,在原型中添加方法的“正確”方法是什么......

沒有一個。 用一些其他對象替換默認原型似乎有點浪費,但是分配由文字創建的對象可能更整潔,更容易閱讀順序分配。 對於一個或兩個作業,我會使用:

 Constructor.prototype.method = function(){…}

但是對於很多方法我會使用對象文字。 有些甚至使用經典的擴展​​功能,並做:

myLib.extend(Constructor.prototype, {
    method: function(){…}
});

如果已經定義了一些方法,那么添加方法是有益的。

看看一些圖書館並決定你喜歡什么,一些混合搭配。 做任何適合特定情況的事情,通常只需要獲得足夠的代碼就可以看到相同的內容,然后無論您選擇何種模式,它都會看起來很整潔。

fAfB實際上是相同的,這只是一個慣例問題。

如果只有一個對象的實例,我甚至不會使用構造函數,而只是一個對象文字,例如:

var o = {
   fA: function () { ... },
   fB: function () { ... },
   fC: function () { ... }
};

至於將它添加到實例或原型中,如果你只有一個實例,那么實例比將它添加到原型更有效,但正如我所說,使用文字代替。

我避免在構造函數中聲明函數,因為構造函數的每次調用都將創建表示每個函數的新對象。 這些對象不是很大,如果創建了很多對象,它們往往會相加。 如果可以將函數移動到原型,那么這樣做會更有效。

至於添加到原型,我贊成

TestObject.prototype.functionName = function () { };

風格,但這是一個偏好的問題。 我喜歡上述內容,因為無論是擴展原型還是創建初始原型,它看起來都是一樣的。

我回答第一部分:沒有區別,當你聲明函數不是變量時,它的聲明在塊中上升,所以

...
func();
...    
function func () { ... }

等於

var func = function () { ... };
...
func();
...

所以你的代碼

function TestObject () {
  this.fA = function() { // do stuff };   
  this.fB = testB;    
  function testB() { // do stuff }
}

等於

function TestObject () {
    var testB = function () { // do stuff };    
    this.fA = function () { // do stuff };
    this.fB = testB;
}

還有關於JavaScript如何在低級別運行的任何明確的JavaScript樣式指南或文檔嗎?

該死的javascript程序員應該錯過“面向Web開發人員的專業JavaScript” 這本書很精彩,深入探討。 它解釋了對象,類仿真,函數,范圍等等。 它也是一個JS參考。

從技術上來說,每次都按照我上面的方式或者調用TestObject.prototype.functionName = function(){}的方式向原型添加方法的“正確”方法是什么?

至於定義類的方法,我建議看看各種JS MVC框架(如Spine.js,它是輕量級的)。 您不需要整個它們,只需要它們的類仿真庫 這樣做的主要原因是JS沒有類的概念,而是純粹由對象和原型組成。 另一方面,可以完美地模擬類(請不要模仿,因為它是缺少的東西)。 由於這需要程序員的一些規則,最好有一個類仿真庫來完成這項工作並使代碼更清晰。

程序員應該期望類仿真庫的標准方法是:

// define a new Class
var AClass = Class.create({
   // Object members (aka prototype), 
   // usually an initialize() method is called if it is defined 
   // as the "constructor" function when a class object is created
}, {
   // Static members
}); 

// create a child class that inherits methods and attributes from parent
var ChildClass = AClass.extend({
   // Child object members
},{
   // Child static members
}); 

AClass.include({
   // Object amendments (aka mixin), methods and attributes 
   //   to be injected to the class object
},{
  // Statics amendments, methods and attributes to be 
  //  injected as class static members
});


// check object type
var aObj = new AClass();
aObj instanceof AClass; //  true
aObj instanceof ChildClass; //  false


var cObj = new ChildClass();
cObj instanceof AClass; //  true
cObj instanceof ChildClass; //  true

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM