2012-11-29 49 views
3

[編輯:vector2dvector3d都不是很好的例子。我現在使用ptptMass。]Javascript Inheritance with new Arguments

我一直在尋找答案,但似乎沒有好的解決方案。

假設我有一個對象如下。

function pt(x,y){ 
    this.x = x; 
    this.y = y; 
} 

現在,我想有一個質量如下。

function ptMass(x,y,m){ 
    this.x = x; 
    this.y = y; 
    this.m = m; 
} 

最好使用繼承來創建ptMass類。

我目前使用以下方式來做到這一點。

function ptMass(x,y,m){ 
    pt.apply(this.arguments); 
    this.m = m; 
} 

是否與prototype這樣做的呢? 我試過以下,但它不起作用。

pt = function(m){this.m = m}; 
ptMass.prototype = new pt(); 

還有一個問題,使用原型繼承的進展是什麼?

+1

我不喜歡你的方法,或者至少不是你的具體樣品中,因爲它違反了基本原則:一個「verctor 3D」是不是「矢量2D」。我認爲你所看到的是參數化 – jodarove

回答

3

首先,爲什麼繼承它更好?
我得到了幾個繼承的參數,但我更喜歡自己組合(模塊/組件和依賴注入)。

其次,你會得到重用出來做的:

function Vector2D (x, y) { 
    this.x = x; 
    this.y = y; 
} 


function Vector3D (x, y, z) { 
    Vector2D.call(this, x, y); 
    this.z = z; 
} 

第三,在一個大型JS應用,創造數萬個多邊形十萬(或數百萬),額外的函數調用只是將放緩它不必要地下降。

第四,你不能使用

Vector3D.prototype = new Vector2D(); 

首先,你不初始化xy到的Vector2D裏面什麼。
二,prototype是爲了容納靜態屬性和功能,如果你來自其他語言。

即使你沒有初始化Vector2D,它仍然將是您的Vector3D類的每個實例的完全相同的Vector2D。

爲什麼不乾脆:

var point2D = function (x, y) { 
     return { x : x, 
       y : y }; 
    }, 
    point3D = function (x, y, z) { 
     return { x : x, 
       y : y, 
       z : z }; 
    }; 

...當你有這些特定的建築塊作爲基本元素,構成其使用它們不同的模塊?


編輯

function anObj (x, y) { 
    var privateFunc = function() { return y; }; 

    return { 
     x : x, 
     method : function() { return privateFunc(); } 
    }; 
} 


var myObj = anObj(1, 2); 
myObj.x;  // 1 
myObj.method(); // 2 

這裏的好處是,你現在得到私有變量(privateFuncy)。
不足之處在於,就內存使用情況而言,您的對象的每個實例都需要擁有其所有私有方法副本的OWN副本。
所以,如果你正在做成千上萬的這些對象(頂點/多邊形,例如),他們不NEED有私有狀態,這是不使用的方法。

但是,如果你讓玩家或敵人,或控制器,或任何你切勿想篡改,那麼你要使用這樣的(或更高級)的方法。

如果你有一個情況下,你可能想STATIC數據/方法這也是100%的私有,那麼你應該嘗試這樣的格式:

var objectMaker = (function() { 
    var staticData = 32, 
     staticFunc = function (num) { return num + staticData; }; 

    return function (x, y) { 
     var privateData = 12, 
      privateMethod = function (num) { 
       return y + privateData + staticFunc(num); 
      }; 

     return { x : x, 
       method : function (num) { return privateMethod(num); } 
     }; 
    }; 
}()); 


var myObj = objectMaker(3, 4); 
myObj.x;   // 3; 
myObj.method(12); // 12 + y(y === 4) + privateData + staticData; 

所以我們做了什麼這裏是我們有一個立即觸發功能(只要定義它就會觸發,並將函數的值返回給變量)。
因此,在我們的特殊情況下,該函數立即返回我們想要用來創建新實例的實際的函數。

私有變量,是直接作用(不是我們返回構造函數)的內部功能是靜態的,在您創建將有關閉內獲得完全一樣的功能/數據每個實例。
不足之處在於那些靜態函數有訪問私有數據(甚至是特定於實例的數據)的訪問權限。
這意味着您必須將您的值傳遞給靜態函數,並捕獲靜態函數的返回值,因爲您不能依賴靜態方法來修改實例值(從技術上講,您可以直接修改對象/數組如果你將它們傳遞給函數,否則你必須捕獲返回值)。

現在,您可以擁有大量幫助程序功能,這些功能在實例(較低內存)之間共享,同時仍然是私密和安全的。

如果你想要的是公共屬性,公共方法,和靜態方法/屬性,那麼你可以像這樣訪問他們:

var Obj = function (x, y) { 
    this.x = x; 
    this.per_instance_method = function() { return y; }; 
}; 

Obj.prototype.staticData = { z : 32 }; 
Obj.prototype.staticMethod = function() { return this.x + this.staticData.z; }; 

var myObj = new Obj(3, 4); 
myObj.staticMethod(); 

...只是不要指望任何原型的方法來訪問到任何實例的私人數據(如y)。

+0

謝謝諾亞!我有一些後續問題。如果有'var point2D = function(x,y){....'?使用'var point2D = function(x,y){....'over'function point2D(x,y){...'?有什麼優點/缺點? – user1863421

+0

@ user1863421看看編輯 - 希望這有助於。請記住,這些解決方案都不是一刀切的。選擇一個滿足當時你想要工廠的物體的需求。他們需要私人數據/方法嗎?他們是否需要大量可以在所有實例之間共享的幫助方法(需要訪問私人數據)?或者你只需​​要一些簡單的公共對象,以及一些靜態的方法來處理公共狀態? – Norguard

1

不,你的第一個是接近正確的:

function vector3d(x,y,z){ 
    vector2d.apply(this, arguments); 
    // you might also use vector2d.apply(this, [].slice.call(arguments, 0,2)); 
    // or simpler vector2d.call(this, x, y); 
    this.z=z; 
} 

所以,是的,你必須構造函數調用它。調用一次創建原型對象將正確設置繼承,但創建一個vector2D的實例 - 您既不需要也不需要。它甚至可能會造成傷害。查看What is the reason [not] to use the 'new' keyword [for inheritance]?的詳細解答。

有沒有辦法用原型做到這一點?

vector3d.prototype = Object.create(vector2d.prototype); 

將使原型對象,從中vector3繼承的所有實例,從vector2d原型對象繼承。我不確定你是否需要這樣,通常的二維方法都不適用於三維矢量。

使用原型繼承的進展是什麼?