Проблема эффективности с объектами на основе замыкания - PullRequest
0 голосов
/ 03 марта 2011

Один из способов определить класс в Javascript - с помощью замыканий и литерала объекта. В качестве примера рассмотрим круг:

var circle = function(radius) {
    var radius = radius;
    return {
        area: function() { 
            return Math.PI*(radius*radius); 
        }
    }
}

Объекты Circle могут быть созданы с инкапсулированными внутренними переменными:

c = circle(1);
c.area(); // Returns pi
c.radius; // Returns undefined

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

var Circle = function(radius) {
    this.radius = radius;
}
Circle.prototype.area = function() { 
    return Math.PI*(this.radius*this.radius); 
};

Теперь проблема в том, что переменные не могут быть объявлены закрытыми:

c = new Circle(1); 
c.area(); // Returns pi 
c.radius; // Returns 1

Кто-нибудь знает, как бы я получил лучшее от обоих? Эффективность - это проблема, поэтому лучше избегать текущей формулировки первого метода, и я пишу для открытого API, поэтому не хочу, чтобы пользователи имели доступ к внутренним переменным / методам. Заранее спасибо ...

Ответы [ 2 ]

1 голос
/ 03 марта 2011

Как насчет этого:

function Circle(radius) {
    this.getRadius = function() { return radius; }
}

Circle.prototype.area = function() {
    var r = this.getRadius();
    return Math.PI * r * r; 
};

Теперь каждый экземпляр псевдокласса Circle имеет два метода:

  • area, который унаследован от прототипа, что делает его публичным методом
  • getRadius, который назначается объекту экземпляра, что делает его методом экземпляра

Значение radius все еще можно получить через getRadius. Однако, если getRadius сможет определить, вызывается ли он из метода Circle.prototype, и вернуть значение radius, только если оно есть, то это решит его, но я не уверен, что это можно сделать.

0 голосов
/ 03 марта 2011

Это то, что я придумал, хотя вопрос о том, является ли создание метода GetArea () каждый раз «эффективным», я сомневаюсь, но это единственный способ, которым я знаю, получить доступ к локальной переменной области действия из методов-прототипов:

var Circle = (function(){
    var Circle = function(radius) {
        this.GetRadius = function(){
            return radius;
        }
    };
    Circle.prototype.area = function() {
        var rad = this.GetRadius();
        return Math.PI*(rad*rad); 
    };
    return function(radius){
        return new Circle(radius);
    }
})();

(Это позволит получить доступ к значению радиуса круга, но не позволит вам его изменить, поэтому я предполагаю, что вы этого хотели)

...