Есть ли способ внедрить привилегированные методы после создания объекта?
Я пытаюсь написать полностью автоматизированные модульные тесты на JavaScript, и я ищу способ прочитать некоторые частные переменные в различных функциях JS. Я подумал, что вспомнил способ внедрения привилегированных членов в функцию / объект (и обнаружил ошеломляющее вхождение "нет такой вещи, как private в JS"), и все же я не могу найти никаких ресурсов, указывающих как.
Я пытаюсь прочитать свойства .prototype
но если есть способ, кто-нибудь здесь будет знать, куда направить меня быстрее, чем я сам найду.
Спасибо
Обновить
Привилегированный означает функцию, которая может использоваться извне объекта и имеет доступ для чтения "закрытых" переменных (переменные, которые иначе не могут быть прочитаны извне). См. http://javascript.crockford.com/private.html для объяснения Крокфорда.
Пример функции, которую я пытаюсь внедрить, это
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
,