Javascript 如何创建函数的模型?

Javascript 如何创建函数的模型?,javascript,class,model,inheritance,Javascript,Class,Model,Inheritance,我想创建一个类的模型 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 c

我想创建一个类的模型

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;
  }
}

如何做到这一点?

您试图实现的是继承,因为JavaScript不像Java、C#和其他语言那样基于类,而且它基于原型,所以实现起来并不容易

实现这一目标的方法有很多:

一种方法是使用诸如、或之类的框架。然后在模型类中,基本上可以使用
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;
   }
});

在邮报上读到它。祝你好运

不需要任何额外的库就可以做到这一点-它只是有点冗长而已

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());

首先设置一个
car
类并给它一些方法(
setColor
setMake
setModel
):

然后您可以从汽车继承:

function volvo( model ){
    console.log( 'volvo constructor' );
    car.call( this, 'volvo', model );
}
volvo.prototype = Object.create( car.prototype );
volvo.prototype.constructor = volvo;
然后查看各个部分:

  • 函数volvo(model){}
    定义了一个
    volvo
    类。
    • 在构造器
      car.call中调用(此为“沃尔沃”车型)
      用于调用父类的构造函数,该构造函数具有固定的
      volvo
  • volvo.prototype=Object.create(car.prototype)设置要从
    汽车继承的
    沃尔沃
  • 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() );
输出为(包括显示何时调用构造函数的日志条目):

如果您需要为
对象创建polyfill,则可以使用:

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()
    }
  })()
}

也许你会发现这也很有趣:


你是说伪经典类实例关系吗?除非你有某种面向公众的方法或属性允许访问所讨论的颜色,否则没有。你可以使用Resig helper函数,但了解构造函数和原型在JavaScript中的工作原理可能是个好主意。也许这个答案可以帮助解决这个问题:有趣的方法,我如何制作10个VW实例?因为Car.extend返回一个实例而不是构造函数,所以你不能执行
myoldbetle=new VW(1972)其中1972年是它的建成年份。再说一遍,你如何创建一堆VW实例呢?人们总是试图让JS像java一样工作,对我来说,这不是JS的重点。拥抱IT原型系统,不要认为“是”,“习惯于A,现在是另外一回事”,它是对JavaScript的敬意,你可以使它工作得像java、C++或C语言这样的SUDO经典语言。事实上,C#已经复制了好几次。你不必把孩子和洗澡水一起扔掉。构造函数初始化是一件非常有用的事情。创建实例时,需要在某个点初始化对象,这意味着设置实例特定的成员。很公平,在这个实例中,extend应该称为copy。请不要通过创建父实例的新实例来继承原型部分,如果您需要对旧浏览器的支持,请改用Object.create并对其进行多边形填充。如果您的继承深入到3个级别,那么如果孙子调用
this.\uuuuu super\uuuuu.constructor.call(this,args)this
是孙子,而
this.\uuuu super\uuu
将引用子构造函数(而不是父构造函数)。您将有一个不断循环的子构造函数调用自己。而是使用
Child.parent=parent.prototype和构造函数中的do:
Child.parent.constructor.call(this,args)
car constructor
This is a Red Ford Fiesta car
volvo constructor
car constructor
This is a Grey volvo S10 car
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()
    }
  })()
}
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"});
// ...