Доступ внутренние функциональные переменные в JavaScript

Во многих платформах внутренние функциональные переменные используются в качестве частных переменных, например

Raphael = (function(){
    var _private = function(a,b) {return a+b;};
    var _public = function(a) {return _private(a,a);}
    var object = {mult2:_public};
    return object;
})();

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

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

Мне нужен к модульным тестам некоторый объект Raphael использование внутренне (в вышеупомянутом примере, я хочу выполнить модульные тесты на объекте private). Как я могу протестировать их?

править: Я получил комментарии о модульных тестах, которые, как предполагается, тестируют открытые интерфейсы.

Позвольте мне указать вариант использования. Я пишу названную библиотеку Raphael. Эта библиотека, как предполагается, добавляет только единственное имя к глобальному пространству имен и ничему больше. Это - специфическое требование для JavaScript, так как JavaScript не имеет пространств имен.

Скажем, Raphael использует связанный список. Если бы JavaScript имел понятие пакетов, то я сделал бы

require 'linked_list'
Raphael = (function(){/* use linked list */})();

Однако JavaScript не позволяет мне делать это всегда, которое не загрязнило бы глобальную область видимости объектом связанного списка! Я поэтому обязан встроить linked_list в локальный объем Raphael:

Raphael = (function(){
    /* implement linked list */
    var linked_list = function(){/*implementation*/};
})();

И теперь я хочу протестировать linked_list реализация.

9
задан Elazar Leibovich 6 May 2010 в 04:27
поделиться

4 ответа

лучшее решение, которое я придумал:

В исходном файле Javascript используйте

Raphael = (function(){
// start linked_list
    var linked_list = function() {/*...*/};
// end linked_list
    var object = {mult2:_public};
    return object;
})();

Теперь используйте сценарий для извлечения объектов между // start ([a-zA-Z _] *) и // end ([a-zA-Z _] *) и модульное тестирование извлеченного кода.

Очевидно, невозможно получить доступ к переменным во внутренней области действия функции из внешней области. Как написано в вопросе SO, на который Джейсон ссылается в комментариях.

1
ответ дан 4 December 2019 в 13:46
поделиться
var Raphael;
var test = true; //or false;

Raphael = (function(){
    var private = function(a,b) {return a+b;};
    var public = function(a) {return private(a,a);}
    var object = {mult2:public};

    if (test) Raphael.private = private;

    return object;
})();
0
ответ дан 4 December 2019 в 13:46
поделиться

Попробуйте следующее:

var adder = function(a,b) {
    return a + b;
}

Raphael = function(fn){
    var _private = function(a,b) {
        fn(a,b);
    }

    var _public = function(a) {
        return _private(a,a);
    }

    var object = {doubleIt: _public};

    return object;
}(adder);

Небольшая инъекция функции

2
ответ дан 4 December 2019 в 13:46
поделиться

Вы все еще упускаете суть.

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

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

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

var Raphael= function(listIterator) {
  listIterator.method();
}(new ListIterator());

Ложные взломы, подобные показанным ниже, совершенно неуместны (в модульных тестах или где-либо еще).

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

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

Что касается отправленного вами кода, вы забыли var , пропустили точку с запятой и использовали два зарезервированных слова в качестве идентификаторов: private и public .

Следствием неиспользования var является возможность возникновения ошибок и проблем, связанных с различными реализациями нестандартных объектов типа GlobalScopePolluter («Объект не поддерживает это свойство или метод. "видел в IE).Последствием использования FutureReservedWord является SyntaxError . Реализация может обеспечить расширение синтаксиса до , разрешить FutureReservedWord в качестве идентификатора, и многие так и делают, однако лучше не полагаться на такие расширения, и если вы получите ошибку, это будет полностью ваша вина.

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

// DO NOT USE THIS CODE.
var Raphael = (function(){
    var _private = function(a,b) {return a+b;};
    var _public = function(a) {return _private(a,a);};
    var object = {mult2:_public};
    return object;
})();

var leakedFunction;

// Spurious hack:
//   Give valueOf a side effect of leaking function.
//   valueOf is called by the _private function as a
//   side effect of primitive conversion, where 
//   ToPrimitive(input argument, hint Number) results 
//   in calling valueOf.

function valueOfSnoop(){ 
    leakedFunction = leakedFunction || valueOfSnoop.caller || function(){};
    return 2;
}

var a = {
  valueOf : valueOfSnoop
};

Raphael.mult2(a, 3);
var privateMathod = leakedFunction;
alert(leakedFunction(1, 2));

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

12
ответ дан 4 December 2019 в 13:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: