JavaScript类/对象可以有构造函数吗?它们是如何产生的?


当前回答

这是一个构造函数:

function MyClass() {}

当你这样做时

var myObj = new MyClass();

MyClass被执行,并返回该类的一个新对象。

其他回答

http://www.jsoops.net/对于Js中的oop非常好。提供私有、受保护、公共变量和函数,并具有继承特性。示例代码:

var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public

    pri.className = "I am A ";

    this.init = function (var1)// constructor
    {
        pri.className += var1;
    }

    pub.getData = function ()
    {
        return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
        + ", ID=" + pro.getClassId() + ")";
    }

    pri.getClassName = function () { return pri.className; }
    pro.getClassName = function () { return pri.className; }
    pro.getClassId = function () { return 1; }
});

var newA = new ClassA("Class");

//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)

//***You can not access constructor, private and protected function
console.log(typeof (newA.init));            // undefined
console.log(typeof (newA.className));       // undefined
console.log(typeof (newA.pro));             // undefined
console.log(typeof (newA.getClassName));    // undefined

例如:http://jsfiddle.net/FZ5nC/

试试这个模板:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
  v1: null
 ,v2: null
 ,f1: function Name_Space_ClassName_f1(){}
}

//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;

//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>

如果你定义一个静态类,你必须调整你的命名空间:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>

示例类:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
    this.Width = width;
    this.Height = height;
    this.Color = color;
}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
  Width: null
 ,Height: null
 ,Color: null
 ,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
    var canvas = document.getElementById(canvasId);
    var context = canvas.getContext("2d");
    context.fillStyle = this.Color;
    context.fillRect(x, y, this.Width, this.Height);
 }
}

//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;

//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
    return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
    return new Shape.Rectangle(50,25,'#ff0000');
}
</script>

示例实例化:

<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");

var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);

var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);

Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>

注意函数定义为A.B = function A_B()。这是为了使您的脚本更容易调试。打开Chrome的Inspect Element面板,运行这个脚本,并展开调试回溯:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};

//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
    A.Func.That.Does.Not.Exist();
}

Fail.Test();
</script>

是的,你可以像这样在类声明中定义构造函数:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

在使用上面Blixt的伟大模板时,我发现它不能很好地使用多级继承(MyGrandChildClass扩展MyChildClass扩展MyClass)——它循环调用第一个父类的构造函数。这里有一个简单的解决方法-如果你需要多级继承,而不是使用this.constructor.super。调用(这,姓氏);使用chainSuper()。调用(这,姓氏);链函数定义如下:

function chainSuper(cls) {
  if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
  var depth = cls.__depth;
  var sup = cls.constructor.super;
  while (depth > 1) {
    if (sup.super != undefined) sup = sup.super;
    depth--;
  }
  return sup;
}

这是一个构造函数:

function MyClass() {}

当你这样做时

var myObj = new MyClass();

MyClass被执行,并返回该类的一个新对象。