Javascript构造函数在“子类”中,正确的表示法?

时间:2016-09-21 17:20:16

标签: javascript function inheritance prototype

我正试图掌握javascript继承。我的示例代码如下所示:

var example = example || {};
example.Classes = {};

(function() {
    var example = example || {};
    example.Classes = {};

    var privateVar = 25;
    function Superclass() {
        this.x = privateVar;
    }
    Superclass.prototype = {
        move: function(x){
            this.x += x;
            console.log("Superclass move",this.x);
        },
        dance: function(x){
            this.x += x*2;
        }
    };

    function Subclass() {
        Superclass.apply(this, arguments);
        this.y = 0;
    };
    Subclass.prototype = Object.create(Superclass.prototype);
    Subclass.prototype.constructor = Subclass;

这是成功的延续:

    Subclass.prototype.dance = function(x, y) {
      this.x -= (x + privateVar);
      this.y -= y;
      console.log("Subclass dance", this.x, this.y)
    };
    example.Classes.Superclass = Superclass;
    example.Classes.Subclass = Subclass;
    window.example.Classes = example.Classes;
}());

var success = new example.Classes.Subclass();
success.dance(5,4);
success.move(6);

控制台输出:子类舞-5 -4 控制台输出:超类移动1


现在继续失败 - 这里有什么不对?为什么我不能用这种方式编写子类构造函数?

    Subclass.prototype = {
        dance: function(x, y) {
            this.x -= (x + privateVar);
            this.y -= y;
            console.log("Subclass dance", this.x, this.y)
        }
    };

    example.Classes.Superclass = Superclass;
    example.Classes.Subclass = Subclass;
    window.example.Classes = example.Classes;
}());

var failure = new example.Classes.Subclass();
failure.dance(5,4);
failure.move(6);  

控制台输出:子类舞-5 -4 控制台输出:错误:failure.move不是函数

1 个答案:

答案 0 :(得分:3)

  

为什么我不能用这种方式编写子类构造函数?

因为您正在吹走以前在Subclass.prototype属性上的对象(来自Object.create(Superclass.prototype)的属性)和替换为对象的原型仅Object.prototype只有一个属性dance

创建Subclass.prototype对象后,您总是希望像以前一样扩充

Subclass.prototype.dance = /*...*/;

替换

// Not this
Subclass.prototype = { dance: /*...*/ };

ES2015添加了一个方便的功能,用于将属性从一个对象(或一系列对象)合并到目标对象中:Object.assign。它可以(大多数情况下)为旧的JavaScript引擎填充。使用它,你可以这样做:

Object.assign(Subclass.prototype, {
    dance: function dance() { /* ... */ },
    skip:  function skip()  { /* ... */ },
    jump:  function jump()  { /* ... */ }
});

已经说过,在2016年,我建议使用ES2015中添加的class功能(如果旧版JavaScript引擎有必要,请进行转换):

class Superclass {
    constructor() {
        //...
    }

    method() {
        // ...
}

class Subclass extends Superclass {
    constructor() {
        super();
        // ...
    }

    anotherMethod() {
        // ...
    }
}