Каков наилучший способ построить объект JavaScript, чтобы он работал и передавал JSLint? - PullRequest
5 голосов
/ 10 июля 2010

Я пытался понять, смогу ли я создавать свои объекты JavaScript настолько интуитивно, насколько это возможно, при этом убедившись, что это настолько «правильно», насколько это возможно.Я управлял множеством различных сценариев через JSLint.com Крокфорда и мне не повезло.Кажется, я исправляю одну ошибку, затем появляется другая ошибка из-за изменений.Ниже примерно так хорошо, как я могу получить.Кто-нибудь может по-другому взглянуть на это?

Это типичный способ структурирования объекта:

function gizmo(id) {

  /* private variables */

  var myId = id;

  /* private methods */

  var init = function () {
    if (myId < 1) {
      setId(1);
    }
  };

  var setId = function (newId) {
    myId = newId;
  };

  // run 'constructor'
  init();

  /* public methods */

  return {
    getId: function () {
      return myId;
    },
    setId: function (newId) {
      setId(newId);
    },
    incrementId: function (inc) {
      setId(myId + inc);
    }
  };
}

// creating an instance of gizmo

var myGizmo = gizmo(-2);
console.log(myGizmo.getId()); // outputs 1

myGizmo.setId(5);
console.log(myGizmo.getId()); // outputs 5

myGizmo.incrementId(2);
console.log(myGizmo.getId()); /// outputs 7

Кажется, это хорошо работает.Тем не менее, когда я запускаю это через JSLint, он выдает ошибку, в которой говорится, что две мои закрытые функции - «Подразумеваемые глобальные переменные».

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

function gizmo(id) {

  /* private variables */

  var myId = id,
      init,
      setId;

  /* private methods */

  init = function () {
    if (myId < 1) {
      setId(1);
    }
  };

  setId = function (newId) {
    myId = newId;
  };

  // run 'constructor'
  init();

  /* public methods */

  return {
    getId: function () {
      return myId;
    },
    setId: function (newId) {
      setId(newId);
    },
    incrementId: function (inc) {
      setId(myId + inc);
    }
  };
}

Ответы [ 4 ]

3 голосов
/ 10 июля 2010

JSLint ожидает, что setId будет определен до того, как на него будет ссылаться в init.

Это передает JSLint.

function gizmo(id) {

  /* private variables */

  var myId = id;

  /* private methods */

  var setId = function (newId) {
    myId = newId;
  };

  var init = function () {
    if (myId < 1) {
      setId(1);
    }
  };

  // run 'constructor'
  init();

  /* public methods */

  return {
    getId: function () {
      return myId;
    },
    setId: function (newId) {
      setId(newId);
    },
    incrementId: function (inc) {
      setId(myId + inc);
    }
  };
}
1 голос
/ 10 июля 2010

Я уверен, что это ошибка в JSLint. Он еще не видел setId, поэтому предполагает, что он глобален. Но в действительности это не имеет значения, потому что все var подняты, согласно ECMAScript 5 10.5 . Это означает, что ваш первый пример и второй семантически одинаковы. Объявление локальной переменной в любом месте в функции обрабатывается немедленно, и привязка изначально имеет значение undefined. Но к тому времени, когда функция (например, init) фактически выполняется, закрытое значение больше не равно undefined.

Чтобы увидеть, что setId изначально не определен, но никогда не относится к глобальному, выполните этот тест:

function setId()
{
  alert("Global setId");
}
function f()
{
  var init = function()
  {
    setId();
  }
  alert(typeof(setId));
  init();
  var setId = function()
  {

  }
}

Он выдаст неопределенное сообщение, а затем выдаст ошибку TypeError.

0 голосов
/ 10 июля 2010

Прошло много времени (несколько лет) с тех пор, как я серьезно программировал JavaScript, поэтому моя память о деталях передового опыта совершенно исчезла. То, что я сделал, вернулось назад и выкопало несколько ресурсов, которые могут помочь вам принять обоснованное решение.

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

0 голосов
/ 10 июля 2010

Я не знаю о JSlint, но после прочтения «хороших частей javascript» я всегда объявляю объекты как литералы.

например:

Mogwai={
  has_crazy_thoughts:True,
  reacts_to_water:True,
  name: 'Gizmo',
  eat:function(food){
    // code
  },
  become_gremlin:function(){
    // code
  },
  cause_havoc:function(){
    // code
  }
}

Вы фактически не декларируете никаких объектов выше. Просто функция. Внутренние функции на самом деле не существуют в Javascript - это совсем не похоже на Java.

РЕДАКТИРОВАТЬ: Я настоятельно рекомендую книгу, упомянутую выше (без принадлежности): http://oreilly.com/catalog/9780596517748 ... она написана Дугласом Крокфордом, который принес нам JSlint.

...