javaScript:揭示原型模式:这两个版本有区别吗?

时间:2014-03-02 18:14:48

标签: javascript revealing-prototype

我通常会看到如下面的语法#2所示的显示原型模式的示例,但我发现语法#1更加一致。除了语法之外,它们有什么不同吗?功能上,性能方面还是其他?

语法#1:

function MyClass1(name){
    this.name = name;
}
MyClass1.prototype = new function () {
    var static = 0;

    var getStatic = function () {
        return static;
    }
    this.incStatic = function () {
        static++;
        return getStatic.call(this);
    }
    this.constructor = MyClass1
};

与#2完全相同:

function MyClass2(name){
    this.name = name;
}
MyClass2.prototype = function () {
    var static = 0;

    function getStatic () {
        return static;
    }
    function incStatic() {
        static++;
        return getStatic.call(this);
    }
    return {
        incStatic:incStatic,
        constructor:MyClass2
    };
}();

这是一个演示完全相同行为的小提琴:http://jsfiddle.net/arctelix/FSk8z/

似乎两种语法都有完全相同的结果。但是,我从未见过如#1所示的例子,所以我不得不想知道为什么?对我来说,#1只是一个更常量的语法,我讨厌在特殊的返回块中识别公共成员。

2 个答案:

答案 0 :(得分:0)

我个人认为重新分配something.prototype是不合适的。相反,扩展原型:

(function() {
    var static = 0;
    MyClass.prototype.getStatic() {return static;}
    MyClass.prototype.incStatic() {return static++;}
})();

答案 1 :(得分:0)

这一切都是因为我正在创建一个利用泛型类构造函数的MVC框架。我使用两种不同的实现方法在Class构造函数的较大上下文中运行这些变体。方法1重新分配方法2扩展它的原型。方法1具有统一的原型链,其中方法2在语法#1的对象原型之上添加函数原型。方法1和方法2的性能大致相同。

蓝&红色=语法#1。

Teal&绿色=语法#2。

黄色& purple =语法#2的变体。

enter image description here

var Class = function (methods, options) {
    //allow for Proper class name to show up in browser devtools
    options = options || {}
    var debug = options.debug || false
    var protoTest = options.protoTest || 0
    var pInternal = options.pInternal || true
    var klassName = methods.constructor.name
    console.log('------protoTest =', protoTest, '/ debugClass =', debug, '/ pInternal =', pInternal, '/ klassName = ',klassName)

    //compile the constructor & internalMembers
    var Class = function () {
        //console.log('Class() is building:', !(init instanceof init))
        //provide inernal object for constructor
        if (pInternal) this.internal = {}
        this.constructor.apply(this, arguments);
        //remove internal from public scope
        if (pInternal){
            var int = this.internal
            delete this.internal
        }
        //populate self with this and internal vars
        if (pInternal){
            var self = {pub:this, int:{}};
            for (var v in int){
                self.int[v] = int[v];
            }
        }else var self = this
        // Instantiate internalMembers with self
        var include = methods.include;
        if (include) include.call(this, self);
    };

    //create constructor function with className (fixes class name in debugger)
    if (debug == true && klassName) {
        var klass = new Function("init", "return function " + klassName + "(){ init.apply(this,arguments) };")(Class);
    }else var klass = Class


    console.log('---type', typeof methods.prototype)
    if (typeof methods.prototype == 'object'){
        //must use traditional revealing prototype
        var prototype = methods.prototype;
        if (protoTest==0){
            //overides prototype
            if (prototype) klass.prototype = prototype;
        }else{
            //does not overide prototype
            for (var p in prototype) klass.prototype[p] = prototype[p]
        }
    }
    //create prototype from Class method
    //----------------test 0
    else if (protoTest==0){
        //overides prototype (new has extra proto in chain)
        var prototype = methods.prototype;
        if (prototype) klass.prototype = new prototype();
    }
    //----------------test 1
    else if (protoTest == 1){
        //does not overide prototype and has uniform chain
        var pms = new methods.prototype()
        for (var p in pms) klass.prototype[p] = pms[p]
    }
    //----------------end test

    //add other Class methods to prototype
    var exclude = ['include', 'initialize', 'prototype'];
    for (var property in methods) {
        if (exclude.indexOf(property) == -1) {
            klass.prototype[property] = methods[property];
        }
    }

    return klass; //return the class
};

所有测试:http://jsperf.com/revealing-proto-test/4

小提琴:http://jsfiddle.net/arctelix/Cp4nG/

还有一个带测试的调试模式:http://jsperf.com/revealing-proto-test/3