2012-06-29 3 views
3

Оригинальный код:Object.prototype Методы и 'Строгая' в IIFE (Сразу-Вызванный Функция Expression)

'use strict'; 
function GitJs(config) { 
    var defaults = { 
     inheriting: false, 
     clientId: undefined, 
     accessToken: undefined, 
     baseUrl: 'https://api.github.com', 
     mode: 'read' 
    }; 

    this.config = $.extend(defaults, config); 
} 

/** 
* Gets the jQuery method that GitJs#generateApiRequest is going to use to send the ajax request. 
* 
* @param {string} httpVerb The HTTP verb that the request will use, 
* @return string 
*/ 
GitJs.prototype.getCommandMethod = function (httpVerb) { 
    var method = $.get; 

    switch (httpVerb) { 
    case 'GET': 
     method = $.get; 
     break; 
    case 'POST': 
     method = $.post; 
     break; 
    } 
    return method; 
}; 

... 

Новый код:

(function() { 
'use strict'; 
    'use strict'; 
    function GitJs(config) { 
     var defaults = { 
      inheriting: false, 
      clientId: undefined, 
      accessToken: undefined, 
      baseUrl: 'https://api.github.com', 
      mode: 'read' 
     }; 

     this.config = $.extend(defaults, config); 
    } 

    /** 
    * Gets the jQuery method that GitJs#generateApiRequest is going to use to send the ajax request. 
    * 
    * @param {string} httpVerb The HTTP verb that the request will use, 
    * @return string 
    */ 
    GitJs.prototype.getCommandMethod = function (httpVerb) { 
     var method = $.get; 

     switch (httpVerb) { 
     case 'GET': 
      method = $.get; 
      break; 
     case 'POST': 
      method = $.post; 
      break; 
     } 
     return method; 
    }; 

    ... 
}()); 

Как этот код стоит, когда Я пытаюсь:

var gitjs = new GitJs();

Я сказал, что GitJs не определено

Какого черта я думал:

  • Я не хочу, чтобы положить use strict внутри каждого метода.
  • Я хочу, чтобы мой код играл хорошо, если он получает миниатюру и объединяется в другой файл.
  • Я хочу использовать синтаксис .prototype для простоты наследования позже (и код ясности)
  • Я не хочу, чтобы сделать глобальную переменную var gitJs, поскольку это может быть преодолено чужим сценарием.
  • Я предполагаю, что пользователь всегда будет вызывать конструктор объекта с помощью ключевого слова new

Для записи, я знаю, что я не прав. Неправильно. Я просто не могу понять, где этот недостаток в моих мыслях лежит, и мне хотелось бы получить какое-то руководство.

ответ

4

Ваша проблема в том, что GitJS теперь является частной переменной непосредственно вызываемой функции. Вы не можете скрыть свою функцию в частной области и сделать ее общедоступной одновременно. Они являются взаимоисключающими целями.

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

var GitJS; 
(function() { 
    'use strict'; 
    GitJS = function(){ ... } 
    ... 
}()); 

или вернуть экспортируемую функцию внутри IIFE.

var ExportedGitJS = (function(){ //using a different name just to be clear... 
    'use strict'; 
    var GitJS = function(){ ... } 
    ... 
    return GitJS; 
}()); 

Хорошо, я соврал. You может сделать модули Javascript без необходимости полагаться на глобальные переменные, но это обычно означает использование другого соглашения о создании модуля и/или использование библиотеки модулей. Я бы очень рекомендовал вам ознакомиться с http://requirejs.org/, если вы заинтересованы в этом.

+0

Я начинаю понимать, что я сделал не так. Что касается глобального var GitJs, как насчет моего оператора 'new'? Или это спорный вопрос, так как конструктор должен получать вызывается IIFE так или иначе? –

+2

Конструктор не будет вызывать IIFE; IIFE является фактически просто оболочкой области для кода, который выполняется процедурно (то есть, сразу). Ваш новый оператор должен работать, если у вас есть GitJS в вашей локальной области, что вы можете сделать, установив глобальный или с помощью загрузчика модуля. – zetlen

2

@missingno является правильным, но я должен добавить, что вы всего на один шаг от использования RequireJS или equivalentloader. Вы правы, чтобы проявлять ненависть к глобальным переменным; если вы обязуетесь выполнять весь свой JavaScript внутри асинхронных модулей с определенными зависимостями, то вы можете просто вернуть конструктор GitJs в глобальную функцию определения, а затем потребовать, чтобы ваш модуль GitJS находился в том, что ему нужно.

// using the global define function provided by an AMD loader 
// assuming that jQuery has already been provided by the paths config 
define(['jquery'],function($) { 
    'use strict'; 
    var GitJS = function() { ... } 
    return GitJS 
}); 
2

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

  • не вставить use strict прагмы в каждом методе
  • не налагать строгий режим на другие источники при объединении
  • использовать синтаксис .prototype
  • не требует глобального var gitJs переменная
  • позволяют пользователю вызывать конструктор объекта с помощью ключевого слова new

Там он:

/* Class constructor, public, globally available */ 
function GitJs(config) { 
    'use strict'; /* You may want to drop this one */ 
    var defaults = { 
     inheriting: false, 
     clientId: undefined, 
     accessToken: undefined, 
     baseUrl: 'https://api.github.com', 
     mode: 'read' 
    }; 

    this.config = $.extend(defaults, config); 
} 

/* IIFE to wrap the *main* strict pragma */ 
(function() { 
    'use strict'; 

    GitJs.prototype.getCommandMethod = function (httpVerb) { 
     /* ... */ 
    }; 

    GitJs.prototype.someOtherMethod = function (someParam) { 
     /* ... */ 
    }; 

})(); 

... 

/* some other block */ 
... { 
    var gitjs = new GitJs(); 
}; 

ли это частично ответить на этот вопрос?

+0

Нет ответа на этот ответ, это, безусловно, способ достижения цели, но действительно ли это лучшая практика? Избиратели голосуют? – chrismarx

+1

через год, я определенно полагаюсь на какое-то глобально доступное пространство имен, где будет храниться класс GitJs', вместо того, чтобы набивать его в «окно». Затем можно определить как конструктор, так и прототипы внутри одного и того же IIFE, защищенного одной «строгой» прагмой, а в конце функции добавить класс в пространство имен. – superjos

Смежные вопросы