2013-12-11 29 views
2

我想創建一個類的模型,假設如何創建功能模型?

var car = function(){ 
    var color; 
    this.setColor = function(clr){ 
    color = clr; 
    } 
} 

現在,我希望有更多的類,例如volvo()。但我也希望所有的東西,car()了,使用它在volvo(),這樣

var volvo = function(){ 
    ...probably some code here 
    this.getColor = function(){ 
    return color; 
    } 
} 

我該怎麼辦呢?

+1

你的意思是僞古典類實例的關係? – gchiconi

+0

除非您有某種面向公衆的方法或屬性允許訪問有問題的顏色,否則不會。 –

+0

您可以使用Resig helper函數,但理解構造函數和原型如何在JavaScript中工作可能是一個好主意。也許這個答案可以幫助那個:http://stackoverflow.com/a/16063711/1641941 – HMR

回答

2

你試圖實現的是所謂的繼承,由於JavaScript不是基於類,如Java,C#和其他語言,它基於原型,它不是很容易實現。

有實現它的方法很多:

一種方法是使用框架,比如Backbone.jsAngularJSEmber.js。然後在你的模型類中,基本上你可以使用Extend關鍵字,然後獲得開箱即用的繼承。

另一種方法是,你有下面的代碼,寫了由John Resig的(jQuery的作者)到應用程序:

/* Simple JavaScript Inheritance 
    * By John Resig http://ejohn.org/ 
    * MIT Licensed. 
    */ 
    // Inspired by base2 and Prototype 
    (function(){ 
    var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; 

    // The base Class implementation (does nothing) 
    this.Class = function(){}; 

    // Create a new Class that inherits from this class 
    Class.extend = function(prop) { 
    var _super = this.prototype; 

    // Instantiate a base class (but only create the instance, 
    // don't run the init constructor) 
    initializing = true; 
    var prototype = new this(); 
    initializing = false; 

    // Copy the properties over onto the new prototype 
    for (var name in prop) { 
     // Check if we're overwriting an existing function 
     prototype[name] = typeof prop[name] == "function" && 
     typeof _super[name] == "function" && fnTest.test(prop[name]) ? 
     (function(name, fn){ 
      return function() { 
      var tmp = this._super; 

      // Add a new ._super() method that is the same method 
      // but on the super-class 
      this._super = _super[name]; 

      // The method only need to be bound temporarily, so we 
      // remove it when we're done executing 
      var ret = fn.apply(this, arguments); 
      this._super = tmp; 

      return ret; 
      }; 
     })(name, prop[name]) : 
     prop[name]; 
    } 

    // The dummy class constructor 
    function Class() { 
     // All construction is actually done in the init method 
     if (!initializing && this.init) 
     this.init.apply(this, arguments); 
    } 

    // Populate our constructed prototype object 
    Class.prototype = prototype; 

    // Enforce the constructor to be what we expect 
    Class.prototype.constructor = Class; 

    // And make this class extendable 
    Class.extend = arguments.callee; 

    return Class; 
    }; 
})(); 

後加載這個代碼,你將能夠使用它爲您的問題:

var Car = Class.Extend({ 
    setColor: function(clr){ 
    color = clr; 
    } 
}); 

var volvo = Car.Extend({ 
    getColor: function() { 
     return color; 
    } 
}); 

閱讀關於它在JavaScript Inheritance by John Resig的帖子。祝你好運!

+0

感謝@ peter-mortensen的編輯。 – ambodi

0
function Car(color) { 
    this.getColor = function() { 
     return color; 
    }; 

    this.extend = function() { 
     function F() {}; 
     F.prototype = this; 
     return new F(); 
    }; 
} 

car = new Car("black"); 
console.log(car.getColor()); 

vw = car.extend(); 
vw.slogan = function() { return "Das Auto"; }; 

console.log(vw.getColor()); 
console.log(vw.slogan()); 

gulf = vw.extend(); 
gulf.isHatchBack = function() { return true; }; 

console.log(gulf.getColor()); 
console.log(gulf.slogan()); 
console.log(gulf.isHatchBack()); 
+0

有趣的方法,我將如何去做10個VW實例? – HMR

+0

你怎麼會認爲它應該完成 – robbmj

+0

由於Car.extend返回一個實例,而不是一個構造函數,所以你不能'myOldBeetle = new VW(1972);'1972年是它建造的那一年。那麼,你將如何創建一堆VW __instances__? – HMR

1

你可以做到這一點,沒有任何額外的庫 - 它只是稍微冗長。

jsFiddle

首先建立一個car類,並給它一些方法(setColorsetMakesetModel):

function car(make,model){ 
    console.log('car constructor'); 
    this.setMake(make); 
    this.setModel(model); 
} 
car.prototype.setColor = function(color){ this.color = color; }; 
car.prototype.setMake = function(make){ this.make = make; }; 
car.prototype.setModel = function(model){ this.model = model; }; 
car.prototype.toString = function(){ return 'This is a ' + this.color + ' ' + this.make + ' ' + this.model + ' car' }; 

然後你可以從車內繼承:

function volvo(model){ 
    console.log('volvo constructor'); 
    car.call(this, 'volvo', model); 
} 
volvo.prototype = Object.create(car.prototype); 
volvo.prototype.constructor = volvo; 

看各個部分,然後:

  • function volvo(model){}定義了一個volvo類。
    • 並在構造函數car.call(this, 'volvo', model);中用於調用父類的構造函數,其固定品牌爲volvo
  • volvo.prototype = Object.create(car.prototype);設置volvo類繼承car類。
  • volvo.prototype.constructor = volvo;用於確保volvo類使用volvo構造函數(沒有以上語句會導致它使用car構造函數)。

然後,我們可以測試:

var c = new car('Ford', 'Fiesta'); 
c.setColor('Red'); 
console.log(c.toString()); 

var v = new volvo('S10'); 
v.setColor('Grey'); 
console.log(v.toString()); 

輸出(包括顯示當構造被稱爲日誌條目):

car constructor 
This is a Red Ford Fiesta car 
volvo constructor 
car constructor 
This is a Grey volvo S10 car 

如果你需要爲Object.create一個填充工具那麼你可以使用:

if (!Object.create) { 
    Object.create = (function(){ 
    function F(){} 

    return function(o){ 
     if (arguments.length != 1) { 
      throw new Error('Object.create implementation only accepts one parameter.'); 
     } 
     F.prototype = o 
     return new F() 
    } 
    })() 
} 
+0

請不要通過創建Parent的新實例來繼承原型部分,而是使用Object.create,如果需要對舊版瀏覽器的支持,請填充它。 – HMR

+0

如果你的繼承深度達到3層,那麼如果GrandChild調用'this .__ super __。constructor.call(this,args);'當'this'是GrandChild和'this .__ super__'時調用Child構造函數,將提及兒童(不是父母)。你將有一個永無止境的Child構造函數循環來調用它自己。而是使用'Child.parent = Parent.prototype;'並在構造函數中做:'Child.parent.constructor.call(this,args);' – HMR

+0

感謝您的提示。 – MT0

0

也許你會發現這也很有趣:http://jsbin.com/IgOCAvI/1/edit

function Car() { 
    this.carData = {}; 
} 

Car.prototype = { 

    set: function(ob) { 
    var obType = Object.prototype.toString.call(ob); 
    if(ob && obType.match('Obj')){ 
     for (var key in ob) { 
     if (ob.hasOwnProperty(key)){ 
      this.carData[key] = ob[key]; 
      // console.log("Stored: "+ key +':'+ ob[key]); // TEST 
     } 
     } 
    }else{ 
     // alert(ob +' ('+obType+')\n is not an Object!'); 
    } 
    }, 

    get: function(key) { 
    if(typeof key == "string"){ 
     var arr = key.replace(/ /g, "").split(','); 
     for(var i=0; i<arr.length; i++){ arr[i] = this.carData[arr[i]]; } 
     // console.log(arr); // TEST 
     return arr; 
    }else{ // Return the whole Object! 
     // console.log(JSON.stringify(this.carData, null, 2)); // TEST 
     return this.carData; 
    } 
    } 

}; 

用法:

// Create new instance of Car 
var car1 = new Car(); 

// Populate with values 
car1.set({manufacturer:"Volvo", model:"S40", color:"green", doors:5, damage:"front fender"}); 
// Get Array collection 
console.log( car1.get("color") );     // [Green] 
console.log( car1.get("color, doors, firstOwner") ); // [Green, 5, undefined] 
// Get whole Object 
console.log( car1.get() );       // [object Object] 
// Get specific value from Object 
console.log( car1.get().color );      // "Green" 
// Let's change a key value 
car1.set({color:"red"}); 
// Test 
console.log( car1.get() ); 


// CAR2 
var car2 = new Car(); 
// let's see if the car2 inherited some property of car1 
console.log(car2.get('color')); // [undefined] // nope. 
car2.set({manufacturer:"Nissan", model:"Micra", color:"gray", doors:3, damage:"none"}); 
// ...