Javascript: экземпляры VAR и статические методы; это нормально с точки зрения памяти? - PullRequest
3 голосов
/ 28 декабря 2010
if (typeof Object.create4 !== 'function') {
    Object.create4 = function (t) {
        var F, f, i, ins = {}, sta = {};

        for(i in t){
            // method: static, means will only exists 1, so is less memory intensive
            if(typeof t[i] === 'function'){
                sta[i] = t[i];
            }
            // vars: instance, means 1 for each object, so is more memory intensive
            else{
                ins[i] = t[i];
            }
        }

        // make a copy of the instances
        ins = jQuery.extend(true, {}, ins);


        F = function() {}
        F.prototype = sta;
        f = new F();

        // assign instances to the instance
        for(i in ins){
            f[i] = ins[i];
        }
        return f;
    };
}

var Vehicle4 = (function(){
    var that = {}

    that.instanceVar = {hey: 1}
    that.staticMethod = function(){
        console.log(this.instanceVar);
    }
    return that;
}())

var v31 = Object.create4(Vehicle4);
var v32 = Object.create4(Vehicle4);

v31.instanceVar.hey = 2;
v31.staticMethod();
v32.staticMethod();

это нормально с точки зрения памяти? Я имею в виду: в 1000 экземплярах будет:

1 * STATICMETHOD 1000 * instanceVar

это эффективно? Я хочу отметить, что instanceVar будет изменен в каждом объекте, поэтому объект signle не будет достаточным.

а могут быть утечки памяти?

var inherit = function(P, C) {
    return jQuery.extend(true, {}, P, C);
}

var Vehicle = function() {}
Vehicle.prototype = {
    init: function(){
        this.instanceVar = {hey: 1}
    },
    staticMethod: function() {
        console.log(this.instanceMember);
    },
    staticMethod3: function() {
        console.log(this.instanceMember);
    }
}

var SuperVehicle = function() {}
SuperVehicle.prototype = inherit(Vehicle.prototype, {
    init: function(){
        this.super.init.call(this);
        this.instanceVar2 = {hey: 1}
    },
    staticMethod: function() {
        console.log(this.instanceVar.hey);
        console.log(this.instanceVar2.hey);
    },
    staticMethod2: function() {
        console.log(this.instanceVar.hey);
        console.log(this.instanceVar2.hey);
    }
});
SuperVehicle.prototype.super = Vehicle.prototype;

var s = new SuperVehicle();
s.init();
s.staticMethod();
s.staticMethod2();
s.staticMethod3();

1 Ответ

1 голос
/ 29 декабря 2010

Я могу точно сказать, что это правильно, и у вас не будет утечек памяти, но в отношении эффективности у меня есть некоторые сомнения.
Во-первых, ваши статические члены не совсем статичны ... они просто добавляются в цепочку прототипов объекта. Вся система наследования прототипов основана на том факте, что каждый объект наследует свой прототип рекурсивно.

Итак, если вы добавите свойство к примитиву Object, например:

Object.prototype.toString = function(){console.log("I am a primitive object");}

все объекты в вашем окне будут наследовать эту функцию, и они будут "примитивными" :)).

Вы можете назвать этот метод "статическим", только если учтите тот факт, что он загружается в память только один раз, а не для каждого экземпляра, но вы не можете считать его статическим, поскольку он взаимодействует с текущим экземпляром объекта (в других объектно-ориентированных языках, если вы поместите ключевое слово "this" внутри статического метода, оно выдаст исключение)

Но я не вижу смысла всего этого в вашем примере.

В вашем примере вы вставляете «статические» методы в прототип объекта, который хотите создать, но вы воссоздаете прототип для каждого экземпляра объекта. Если вы создадите 2 или более экземпляров одного и того же «класса», они не будут совместно использовать прототип, но каждый из них будет иметь идентичные экземпляры.

Это прямо там:

F = function() {};
F.prototype = sta;
f = new F();

Каждый раз, когда вы создаете машины этим методом:

var myVehicle = Object.create4(Vehicle4);
var anotherVehicle = Object.create4(Vehicle4);

Вы создаете прототипы для каждого экземпляра, что в некоторой степени побеждает цель наследования прототипов.

Я бы определенно выбрал классический метод создания объектов (с оператором "new"):

var Vehicle = function(val){this.instanceMember = val;}  
Vehicle.prototype = {   
    "staticMethod": function(){console.log(this.instanceMember);}   
}    
var v1 = new Vehicle("foo");  
var v2 = new Vehicle("bar");

Таким образом, вы можете легко изменить staticMethod и повлиять на все экземпляры Vehicle:

Vehicle.prototype.staticMethod = function(){  
    console.log(arguments[0] || this.instanceMember);  
};

если в вашем примере вы измените staticMethod, изменения будут применены только к экземплярам, ​​созданным после того, как изменение произошло.
Это, как говорится, в этом случае, старый классический способ создания объектов со «статическими» членами гораздо более эффективен.

P.S. : Извините, если я увлекся:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...