2013-12-11 6 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, но может быть хорошей идеей понять, как функции и прототип конструктора работают в JavaScript. Возможно, этот ответ может помочь в этом: http://stackoverflow.com/a/16063711/1641941 – HMR

ответ

2

То, что вы пытаетесь достичь, называется наследованием, и поскольку JavaScript не основан на классах, как Java, C# и других языках, и он основан на прототипах, достичь его не так просто.

Есть много способов ее достижения:

Один из способов заключается в использовании механизмов, таких как Backbone.js, AngularJS или Ember.js. Затем в вашем классе модели в основном вы можете использовать ключевое слово Extend, а затем получить наследование из коробки.

Другой способ заключается в том, что вы включаете следующий код, написал Джон 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 класс и дать ему некоторые методы (setColor, setMake и setModel):

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 

И если вам нужен polyfill для 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

Пожалуйста, не наследуйте часть прототипа, создав новый экземпляр родителя, вместо этого используйте Object.create и заправьте его, если вам нужна поддержка старых браузеров. – HMR

+0

Если ваше наследование идет на 3 уровня, то у вас проблемы, если GrandChild называет 'this .__ super __. Constructor.call (this, args);' когда вызывается конструктор Child, когда 'this' является GrandChild и' this .__ super__' будет относиться к Ребенку (не родительскому). У вас будет бесконечный цикл конструктора Child, вызывающий себя. Вместо этого используйте 'Child.parent = Parent.prototype;' и в конструкторе: 'Child.parent.constructor.call (это, 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"}); 
// ... 
Смежные вопросы