Есть ли способ внедрить привилегированные методы после создания объекта?

Я пытаюсь написать полностью автоматизированные модульные тесты на JavaScript, и я ищу способ прочитать некоторые частные переменные в различных функциях JS. Я подумал, что вспомнил способ внедрения привилегированных членов в функцию / объект (и обнаружил ошеломляющее вхождение "нет такой вещи, как private в JS"), и все же я не могу найти никаких ресурсов, указывающих как.

Я пытаюсь прочитать свойства .prototype но если есть способ, кто-нибудь здесь будет знать, куда направить меня быстрее, чем я сам найду.

Спасибо

Обновить

  1. Привилегированный означает функцию, которая может использоваться извне объекта и имеет доступ для чтения "закрытых" переменных (переменные, которые иначе не могут быть прочитаны извне). См. http://javascript.crockford.com/private.html для объяснения Крокфорда.

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

    var o2 = function() {
        var x = 'me';
    };
    

Обновление 2: Спасибо всем, кто нашел время, чтобы ответить. Я вижу, что подавляющим ответом здесь является "личное - это личное", несмотря на комментарии, которые я вижу в других вопросах SA, где люди говорят, что "в JS нет ничего личного". Я думаю, это больше похоже на риторический комментарий, а не на то, что я надеялся, было какое-то понимание потенциальной лазейки, о которой я еще не знал.

4 ответа

Решение

Правильный ответ на ваш вопрос

Даже если мы попытаемся помочь вам как можно больше, правильный ответ на ваш вопрос прост:

... ты не можешь

Какая польза от переменных замыкания, если бы мы могли получить к ним доступ напрямую из замыкания?

если бы у вас был объект с закрытыми переменными, они не были бы доступны вне функции замыкания, которая является функцией конструктора.

var c = function() {
    var priv = "private";
    this.get = function() {
        return priv;
    };
}

var o = new c();
o.injected = function() {
    return priv; // ERROR!!!!!! priv doesn't exist in function scope
};

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

(function(){

    var intrn = "internal";

    // omit "var" to make it global
    c = function() {
        this.get = function() {
            return intrn;
        };
    };

    // omit "var" to make it global
    o = new c();
    o.injected = function() {
        return intrn; // WORKS
    };
})();

o.injected();

но это отличается от рядовых объектов...

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

function foo(){
    var a = 'a';
    this.addMethod = function(prop, val){
        this[prop] = eval('(' + val.toString() + ')');
    }
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'

Ты можешь использовать eval() в этом случае переопределить функцию в контексте замыкания. Однако, используя eval() опасно, ОСОБЕННО не eval() любой пользовательский ввод, когда-либо. Тем не менее, для использования в тестовом наборе / сценарии это должно быть хорошо.

Я бы посоветовал вам прочитать трактат Крокфорда о том, как достичь привилегированных и приватных объектов javascript.

Если под привилегированным вы подразумеваете методы, которые недоступны за пределами объекта, но которые могут вызываться другими методами и которые на самом деле являются методами объекта, то на самом деле нет никакого способа сделать это, потому что вы помещаете метод в объект, javascript давайте кто-нибудь это назовет.

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

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

Я не думаю, что вы можете сделать это. Рассмотрим следующий код:

function foo() {
    var privateVar = 10;            
    this.privilegedMethod = function() {
         return privateVar;   
    }
}
var obj = new foo();

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

obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"

Но этот новый метод не будет иметь доступа к privateVar,

Другие вопросы по тегам