从原型方法访问构造函数

时间:2014-07-05 01:26:37

标签: javascript constructor scope prototype

在下面的代码中,我有一个Mass构造函数和一些方法。最初,方法在Mass构造函数中,但是我使用的方法很多。因此,为了使事情更有条理,我删除了Mass之外的一些方法,并使用原型添加它们。

但后来我有一个问题。我无法使用Mass引用this;它指的是window

function Mass(elm) {
    this.getElement         = function(element) {
        if (typeof element == "string") {
            return document.getElementById(element);
        }
        return element;
    };
    this.elm                = this.getElement(elm);
    this.elm.style.position = "absolute";
    this.elm.style.left     = 0 + "px";
    this.elm.style.top      = 0 + "px";
    this.updateVars         = function () {
            this.width      = parseInt(this.elm.style.width, 10);
            this.height     = parseInt(this.elm.style.height, 10);
            this.top        = parseInt(this.elm.style.top, 10);
            this.left       = parseInt(this.elm.style.left, 10);
            this.radius     = this.width / 2;
            this.originX    = this.left + this.radius;
            this.originY    = this.top + this.radius;
            this.worldOrgX  = this.originX + parseInt(this.elm.parentNode.style.left, 10);
            this.worldOrgY  = this.originY + parseInt(this.elm.parentNode.style.top, 10);
    };
}

Mass.prototype = {
    // other methods here
    rotation    : {
         // this = window
        mass    : this,
        angle   : 0,
        handler : null,
        rotate  : function (angularVelocity, rotationSpeed) {
                    this.angle = (this.angle + angularVelocity) % 360;
                    // here I need to access Mass.elm and apply rotate
                    this.mass.elm.style.webkitTransform = "rotate(" + this.angle + "deg)";
                },
        start   : function (angularVelocity, rotationSpeed) {
                    var rotation = this; // this = Mass.rotation
                    rotation.handler = setInterval(function () {
                        rotation.rotate(angularVelocity, rotationSpeed);
                    }, rotationSpeed);
                },

    },
}

var earth   = new Mass("earth");
//earth.rotation.start(4.5, 25);

Fiddle

Old version of the code.这很好用。我应该为新的工作做些什么改变?

1 个答案:

答案 0 :(得分:1)

原型并不意味着使构造函数中的代码变小。原型旨在共享共同的功能。例如,对于getElement的所有实例,您的Mass方法都是相同的。因此将它放在原型上是理想的。与updateVars相同。

另一方面,this.rotation是一个对象,而不是一个函数。 Mass的每个实例都将具有不同的this.rotation属性。因此this.rotation无法共享,因此不能放在原型上。

我通常喜欢使用简单的defclass函数在JavaScript中创建“类”:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

defclass函数展开原型并返回其构造函数。顺便说一句,构造函数只是原型上的另一种方法。

所以这就是我如何重写你的Mass类:

var Mass = defclass({
    constructor: function (id) {
        var element = this.element = this.getElement(id);
        var style = element.style;

        style.position = "absolute";
        style.left = 0;
        style.top = 0;

        this.rotation = new Rotation(this);
    },
    getElement: function (id) {
        if (typeof id !== "string") return id;
        else return document.getElementById(id);
    }
});

接下来,我们创建Rotation类:

var Rotation = defclass({
    constructor: function (mass) {
        this.mass = mass;
        this.angle = 0;
    },
    start: function (angularVelocity, delay) {
        var rotation = this;

        setInterval(function () {
            rotation.rotate(angularVelocity);
        }, delay);
    },
    rotate: function (angularVelocity) {
        var angle = this.angle = (this.angle + angularVelocity) % 360;
        var transform = "rotate(" + angle + "deg)";
        var style = this.mass.element.style;

        style.webkitTransform = transform;
        style.mozTransform = transform;
        style.msTransform = transform;
        style.oTransform = transform;
        style.transform = transform;
    }
});

最后,我们只需创建Mass的实例并将其旋转:

var earth = new Mass("earth");
earth.rotation.start(4.5, 25);

自己查看演示:http://jsfiddle.net/NL3SJ/