Можете ли вы расширить объект, имеющий доступ к закрытым свойствам, с помощью функции, которая также может получить доступ к этим закрытым свойствам? - PullRequest
3 голосов
/ 29 августа 2011

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

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

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

Вот немного упрощенного примера кода, который точно отражает мою ситуацию:

//extension object
//fn2 can be any function, with any number of arguments, etc.
var obj1 = {};
obj1.fn2 = function (s1, s2){ console.log(priv); };

//actual object
var obj2 = (function (){
    //private property
    var priv = "hello world";

    //return object
    var obj3 = {};

    //return object's native fn (works)
    obj3.fn = function (s){ console.log(priv); };

    //extension happens here - but is obviously not correct
    obj3.fn2 = obj1.fn2;

    //return object
    return obj3;
})();

//try output
obj2.fn("goodbye world"); //works
obj2.fn2("goodbye world", "thx 4 teh phish"); //fails

Любое понимание будет оценено. И я полностью понимаю, что то, что я хочу, просто невозможно, но, похоже, так оно и должно быть: P

РЕДАКТИРОВАТЬ: Спасибо всем за ответы. Я полностью понимаю, что к свойствам легче получить доступ как к общедоступным, и что обычно унаследованные объекты не будут иметь доступа к ним в противном случае. Однако, поскольку новая функция присоединяется к исходному объекту, я должен верить, что есть способ использовать исходный контекст, а не контекст, в котором была создана новая функция.

Теперь я первый, кто сказал, что eval - это зло, и, на самом деле, я никогда не использовал его или даже не думал об его использовании, прежде. Тем не менее, я пытаюсь сделать все возможное, чтобы сделать эту работу - и я наткнулся на это (на первый взгляд) рабочее решение:

obj3.fn2 = eval (obj1.fn2.toString ());

Итак, если я проверю, чтобы убедиться, что obj1.fn2 является функцией typeof, есть ли способ, который может быть вредным для моего кода? Он не выполняет функцию, поэтому я не вижу, как, но, может быть, я что-то упустил?

Ответы [ 3 ]

2 голосов
/ 29 августа 2011

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

  1. Пересмотрите свой дизайн класса, и подклассы зависят только от открытого интерфейса родительского класса.

  2. Добавление функций получения и установки в открытый интерфейс. Не обязательно лучшая вещь, хотя вы могли бы также обнародовать свойства (помимо вопросов передового опыта и еще много чего)

  3. Просто используйте общедоступные свойства. Это «естественный» способ наследования ОО в Javascript, и обычно он не является проблемой, если вы используете такое дополнение, как добавление подчеркивания в начале имени. В качестве бонуса вы можете использовать функцию наследования прототипов (приятно знать, как использовать ее вместо классов, основанных на замыканиях)

    function Base(){
        this._priv = "Hello world"
    };
    Base.prototype = {
        fn: function(){
            console.log(this._priv);
        }
    }
    
    var obj2 = new Base();
    obj2.fn = function(){ ... }
    
1 голос
/ 29 августа 2011

Я не хочу отвечать на мой собственный вопрос - кажется, что-то вроде фальшивки - но c'est la vie. (потому что я сегодня проснулся по-французски?)

Итак, в то время как я обнаружил, что решение eval (), которое я представил вчера вечером при редактировании моего исходного вопроса, кажется правильным решением и правильным использованием eval для сохранения контекста объекта в рамках новой функции она далека от совершенства.

Во-первых, он работает в FF, но IE и Chrome, похоже, ненавидят его (это были следующие, которые я попробовал, и я перестал пробовать другие после того, как они оба потерпели неудачу). Хотя я уверен, что , вероятно, можно будет работать в разных браузерах, это выглядит как хлопот.

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

В-третьих, .eval () обычно довольно медленный - и получается, что .apply () (который обычно быстрее) может работать достаточно хорошо.

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

Я уверен, что в этом есть что-то большее, чем просто эти 3 вещи, но сейчас я думаю, что я собираюсь пойти с большим количеством «упаковочных» решений - что-то вроде этого:

var f = function (){
    var fauxThis = {};

    fauxThis.priv = priv;

    obj1.fn2.apply(fauxThis, arguments);
};

obj3.fn2 = f;

//(To be placed where I had "obj3.fn2 = obj1.fn2;")

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

Спасибо всем за ваш вклад!

0 голосов
/ 29 августа 2011

Самое быстрое и простое решение состоит в том, чтобы префикс любых предположительно частных свойств подчеркиванием (_).

Лично мне нравится класть мои личные свойства в один объект, который будет помещен на объект, например:

obj.publicProp = 20;

obj._.privateProp = true;

Я бы не стал так сильно беспокоиться об этом, подчеркивание - это в основном универсальный символ для частного, поэтому те, кто использует сценарий, будут знать, что он является закрытым и его не следует трогать. Или, что еще лучше, просто оставьте это вне публичной документации;)

Существуют и другие методы, которые вы можете использовать, которые эмулируют «истинные» защищенные переменные, но они не являются лучшими, поскольку они избегают сборки мусора и могут быть неуклюжими в использовании.

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