javascript中正确的类构造

javascript中正确的类构造,javascript,oop,class,Javascript,Oop,Class,我正在学习Javascript中的OO编程,似乎有很多方法可以创建一个类。我已经设法将我读到的大部分内容提取到一个通用结构中,但我觉得我可能错过了原型设计的目的,从而节省了膨胀。在这个“类”中包含原型定义是否会使它们变得毫无意义(即不减小对象大小)?这个整体结构有什么缺陷吗 谢谢 var Car = (function () { //Private fields var _make; var _model; //Constants (protected by

我正在学习Javascript中的OO编程,似乎有很多方法可以创建一个类。我已经设法将我读到的大部分内容提取到一个通用结构中,但我觉得我可能错过了原型设计的目的,从而节省了膨胀。在这个“类”中包含原型定义是否会使它们变得毫无意义(即不减小对象大小)?这个整体结构有什么缺陷吗

谢谢

var Car = (function () {

    //Private fields
    var _make;
    var _model;

    //Constants (protected by encapsulation)    
    var NUM_OF_WHEELS = 4;

    //Private methods
    function getDesc() {
        return _make + " " + _model;
    }

    //Public constructor
    function thisCar(make, model, color) {
        _make = make;
        _model = model;

        //public properties
        thisCar.prototype.color = color;
    }

    //static properties
    thisCar.carsInTheWorld = 50;

    //static methods
    thisCar.getNumberOfWheels = function () {
        return NUM_OF_WHEELS * thisCar.carsInTheWorld;
    };

    //public properties
    thisCar.prototype.color = "";

    //public method
    thisCar.prototype.startEngine = function () {
        console.log(getDesc() + " engine started");
    };

    return thisCar;
})();
编辑 在阅读了这里提供的评论和链接后,我理解了这一点

需要访问私有成员的类成员不能添加到原型中,并且必须具有特权。同样,通常的做法是在构造函数中不包含原型

var Car = function (make, model, color) {//Public constructor
    //Private fields
    var _make = make;
    var _model = model;

    //Public fields 
    this.color = color; 

    //Private methods
    function getDesc() {
        return _make + " " + _model;
    }

    //Privileged functions (requiring private members) 
    this.startEngine = function () {
        console.log(getDesc() + " engine started");
    };
};

//public method
Car.prototype.sprayPaint = function (newColor) {
    var oldColor = this.color;
    this.color = newColor;
    console.log("Your car has changed from " + oldColor + " to " + newColor);
};

//Public fields  (if not declared in constuctor)
Car.prototype.fuel = 0; 

//static properties
Car.carsInTheWorld = 0;

//static methods
Car.getNumberOfWheels = function () {               
    var NUM_OF_WHEELS = 4;
    return NUM_OF_WHEELS * Car.carsInTheWorld;
};

感谢您的回复,他们真的很有帮助。

大部分都很好。但这一点是错误的:

function thisCar(make, model, color) {
    // [ ... ]
    //public properties
    thisCar.prototype.color = color;
}
在构造函数内部,您不应该为原型分配任何内容。将颜色属性指定给从构造函数创建的所有汽车

相反,请执行以下操作:

    this.color = color;
为了回答一般性问题,以这种方式使用原型并非毫无意义。外部函数仅在脚本解析后运行一次。它将内部thisCar构造函数分配给
Car
。原型属性已正确放置,但上述情况除外

另一个建议是,即使在你的生活中,你也应该使用大写字母作为名字的首字母。我个人也会在这里使用
Car
,因为它看起来更清晰

编辑:

错误比我一开始看到的还要多。这也是错误的

var _make;
var _model;

// [ ... ]
function thisCar(make, model, color) {
    _make = make;
    _model = model;
}
这些不是实例属性


此外,据我所知,没有真正的方法将原型的使用与基于闭包的私有属性结合起来。所以我觉得你们在一起做的太多了

通常的模式是从包含公共访问器/变体的构造函数返回对象,而不是使用原型:

在类定义之外使用原型向其添加属性。您将使用
Car.prototype.myFunc=function(){}Car
之后的code>以将
myFunc
添加到将来实例化的
Car
对象。这些添加的成员是公开的


我应该重申,当代码变大时,使用类框架(如)将为您节省无数麻烦。

您将闭包和面向对象的构造函数混为一谈。通常,你开始时没有结束。在JS中,通过构造函数定义“类”:

var Car = function Car(model) { //Public constructor

    // Private fields of one instance
    // model is an argument
    var make;

    // Private methods of one instance
    function getDesc() {
        return make + " " + model;
    }

    // Public fields of one instance
    this.color = "#555";

    // Public methods of one instance, privileged the access private fields and functions
    this.setMake = function(m) {
        make = m;
    };
    this.desc = function() {
        return getDesc();
    };
} // end of constructor

/* now the prototype things: */   

// public "default" fields, may get overwritten per instance
Car.prototype.color = "";

// public methods, can only access other public things (not "privileged")
thisCar.prototype.startEngine = function () {
    console.log(this.desc() + " engine started");
};
就这样。现在,您可以添加静态内容。它们与
Car
函数无关,但它们通常通过构造函数的being属性获得名称空间。但它们也可以是自由变量

var carsInTheWorld = 50;
// or
Car.livingInstances = 50;
// or something

Car.NUM_OF_WHEELS = 4; // constants are uppercase

只有当您需要静态、私有变量(例如实例计数器)时,才可以围绕所有内容构建闭包。然后,只能从闭包函数内部访问未命名的变量。

将prototype视为直接连接到实例构造函数的方法的备份存储库。如果您试图在没有属性/方法的实例上调用该属性/方法,则会检查该实例的构造函数原型以查找该方法。遗憾的是,prototype属性无法在实例内部看到(访问实例变量)

我鼓励您避免立即攻击链接原型的库,以便允许复杂的类继承方案

主要是因为这种方法往往臭名昭著。它缺乏灵活性,难以阅读,而且不太适合JS首先擅长处理的各种问题。(事实上,这些计划做得太过分了,在任何语言中都是不可取的)。我并不是说继承是不好的,只是JavaScript的圣杯不是写不好的Java,我的意思是20层深度的级联继承集,对于最近没有花几天时间研究它们的人来说是完全不可理解和不可更改的

不要担心封装。不,真的。您最近一次听说前端或UI开发人员在复杂的电子商务站点上重写jQuery的关键内部,或者直接更改JQ对象方法和其他属性,以便对他们正在进行的工作有用,而不必关心其他可能损坏的内容,这是什么时候的事了?正如Python的孩子们所说的“信任用户”。私有实例变量可以帮助澄清什么是接口,什么不是接口。除了这个实用程序,把它放在你的脑海里,在互联网上,每个人都可以随时看到我们的代码


并尽可能了解JS中函数的所有信息。在JS OOP中有很多有用的东西,在JS OOP中,关注的焦点更多的是实例而不是构造函数。函数、上下文和调用/应用方法是构建适合您的结构的关键。

就个人而言,JS中的这种编码让我感到畏缩。这是一种令人难以置信的动态语言,你是对的——做任何事情都有很多方法。我非常希望你最终能使用一个类框架(比如JS.class)。你的代码有很多问题,太多了,无法在这里详细说明。您可以在我的帖子中找到关于JS中正确继承的类型。坦率地说,看到您的代码后,您应该阅读《面向对象JavascriptJuan和Starx入门指南》。这些指南/文章都没有涉及私有变量或方法。同样,我甚至还没有涉及到继承:)但是我必须同意,没有私有变量,这可以写得更好。这可能比重新发明轮子更好。但我喜欢这个问题,因为它迫使我真正理解语言。构造函数不返回对象。是的,对不起,我的结构
var carsInTheWorld = 50;
// or
Car.livingInstances = 50;
// or something

Car.NUM_OF_WHEELS = 4; // constants are uppercase