Javascript, раскрывающий шаблон модуля Noob

Я начинаю читать потрясающую книгу Эдди Османи по шаблонам проектирования javascript, но не могу оторваться от земли. Может ли кто-нибудь сказать мне, что здесь не так с моим подходом (я использую Raphael, просто для удовольствия):

var myPaper = Raphael('container', '800', '600');

var myScene = function() {
  var c1 = myPaper.circle(50, 50, 40);
  var c2 = myPaper.circle(50, 150, 40);
  var c3 = myPaper.circle(50, 250, 40);

  c2.attr("fill", "red");  // yep!

  return {
      firstCircle: c1
  };
}

// at some point later i want to call the function...
myScene();

//  ...then even later I want to refer to one of the circles
//  but without creating another global variable.

myScene.firstCircle.attr("fill", "red");  // nope!
console.log(myScene.firstCircle); //  undefined!

http://jsfiddle.net/aGCv8/


person Ben    schedule 29.01.2013    source источник
comment
У вас нигде не определена переменная circ1, только c1.   -  person Dominic Barnes    schedule 29.01.2013
comment
@dominic верно, это опечатка. не проблема, хотя ... Я исправил это.   -  person Ben    schedule 29.01.2013


Ответы (1)


"Что не так с вашим подходом", так это то, что это не шаблон модуля, раскрывающие или иные. Если вы хотели использовать его, используйте его и сделайте эту функцию самовызываемой:

var myScene = function() {
  var c1 = myPaper.circle(50, 50, 40);
  var c2 = myPaper.circle(50, 150, 40);
  var c3 = myPaper.circle(50, 250, 40);

  c2.attr("fill", "red");  // yep!

  return {
      firstCircle: c1         // ← refer to a variable which is actually defined
  };
}();                          // ← parens go here

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

console.log(myScene.firstCircle); // z {0: circle.[object SVGAnimatedString], node: circle.[object SVGAnimatedString], id: 0, matrix: cb, realPath: null, paper: j…}

Как вы обнаружили, отсутствие скобок (которые вызывают анонимную функцию) приводит к совершенно другому результату.

http://jsfiddle.net/mattball/qR4Fj/

person Matt Ball    schedule 29.01.2013
comment
Большое спасибо, Мэтт. Дело в том, что я на самом деле хочу иметь возможность вызывать функцию позже, с общедоступным указателем. Когда я реорганизую ваш код, чтобы сделать это, я получаю аналогичную проблему: jsfiddle.net/wUbG2 - person Ben; 29.01.2013
comment
Почему вы хотите иметь возможность вызвать его позже? Модуль не должен быть функцией; это автономная логическая единица со связанными функциями. Если вы хотите, чтобы его можно было повторно использовать и применять к разным местам на странице, не создавайте и не используйте модуль. Создайте и используйте класс. - person Matt Ball; 29.01.2013
comment
Ну, это называется позже в зависимости от кучи условных факторов. (Я сильно упрощаю для примера.) Его не нужно повторно использовать или вызывать несколько раз. Не для того, чтобы отклоняться от темы, но также: мое понимание javascript заключается в том, что в нем нет классов. Я действительно просто пытаюсь понять, почему myScene.secondCircle возвращает значение undefined во второй скрипке... - person Ben; 29.01.2013
comment
myScene.secondCircle не определено, потому что c2 равно undefined, когда возвращается объект, определяющий renderCircles и secondCircles. А занятия точно есть! developer.mozilla.org/en-US/docs/JavaScript/ - person Matt Ball; 29.01.2013
comment
Да, renderCircles() определяет c2, но поскольку вы не используете замыкание, ссылка объекта на c2 после этого магическим образом не обновляется. Вы можете исправить это, выполнив следующие действия: jsfiddle.net/mattball/zQh9V - person Matt Ball; 29.01.2013