Escrevendo uma biblioteca Javascript que seja amigável para preenchimento e inspeção de código
-
23-09-2019 - |
Pergunta
Recentemente criei minha própria biblioteca Javascript e inicialmente usei o seguinte padrão:
var myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
O problema com isso é que não posso realmente usar o preenchimento de código porque o IDE não conhece as propriedades que a função literal está retornando (a propósito, estou usando o IntelliJ IDEA 9).
Eu olhei o código jQuery e tentei fazer isso:
(function(window, undefined) {
var myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
window.myLibrary = myLibrary;
}(window));
Eu tentei isso, mas agora tenho um problema diferente.O IDE realmente não entende myLibrary
qualquer.
A maneira como estou resolvendo o problema agora é desta forma:
var myLibrary = {
func: function() { },
func2: function() { },
prop: ""
};
myLibrary = (function () {
var someProp = "...";
function someFunc() {
...
}
function someFunc2() {
...
}
return {
func: someFunc,
fun2: someFunc2,
prop: someProp;
}
}());
Mas isso parece meio desajeitado e não consigo entender exatamente como o jQuery está fazendo isso.Outra dúvida que tenho é como lidar com funções com números arbitrários de parâmetros.
Por exemplo, jQuery.bind
pode receber 2 ou 3 parâmetros, e o IDE não parece reclamar.Tentei fazer a mesma coisa com minha biblioteca, onde uma função poderia receber 0 argumentos ou 1 argumento.Porém, o IDE reclama e avisa que o número correto de parâmetros não está sendo enviado.Como faço para lidar com isso?
EDITAR
Estou começando a me perguntar se esse é um problema do Idea9 porque o jQuery tem o mesmo problema.Parece que não tenho esse problema em outros projetos.
Solução
Estou usando a ideia com o padrão do módulo Yahoo e minhas obras de preenchimento automático. Google Padrão do módulo Yahoo.
http://www.yuiblog.com/blog/2007/06/12/module-pattern/
http://ajaxian.com/archives/a-javascript-module-pattern
TEST = function() {
var SOME_CONSTANT='asd';
function privateStuff(){
var a = 'asd';
return a;
}
return{
someArray:[],
someMethod: function(foo, bar){
var foo = *1
}
,
myProperty:'test'
}
}();
TEST.*2
com *1 e *2, marquei locais onde tentei concluir automaticamente.
Em *1 eu recebo um método de algum_constant e privatestuff e, se eu colocar isso. (AutoComplete), tenho acesso a todos os métodos e propriedades dentro do retorno {} bloco
Quando tento preenchimento automático no *2, recebo todos os métodos e propriedades no bloqueio de retorno {}. Alguns métodos do Concome e Privatestuff são Invisibile lá, porque são "privados".
Para mim, esse nível de preenchimento automático é muito bom.
Outras dicas
Eu acho que será ótimo se você ler algo sobre Douglas Crockford. Ele é o arquiteto na estrutura de Yahou Yui. E depois disso, você pode ter uma idéia melhor de como criar uma ótima estrutura. E para o parâmetro, existem 2 opções. 1.- Enviar por exemplo do objeto
{ option :{ var1 : "value" , var2:"value"}, var3 : "value" }
E você pode verificar se a opção existe.
O segundo que não é ótimo é verificar se o parâmetro é indefinido.
function foo(var1,var2){
var var1_this = null;
if(var1 != undefined)
var1_this = var1;
}
E apenas um comentário, por que construir uma nova estrutura JavaScript? Use protótipo, jQuery, mootols, yui. Por que reinventar a roda?
Isto é uma resposta aos comentários feitos postagem de mwilcox.
Esse exemplo realmente funcionará.Desde myLibrary
é definido sem var
, ele é automaticamente colocado no namespace global e acessível como tal.Através do fechamento criado pela função autoexecutável, as variáveis e métodos privados ainda estão acessíveis no myLibrary
métodos.Você pode tentar isso facilmente colocando-o no Firebug ou Rhino.
Hoje em dia, não costumo esconder minhas variáveis, ou seja,Eu uso o padrão Pseudoclássico ou o padrão Prototípico e prefixo meu pretendido métodos privados com um _
:
// Pseudoclassical pattern
function Hello() {}
Hello.prototype = {
method1: function() {},
method2: function() {},
_pseudeoPrivate: function() {}
};
/* Prototypal pattern. To create multiple instances of this object,
you need a helper function such as
function beget(o) {
var F = function() {};
F.prototype = o;
return new F;
}
var instance = beget(world);
*/
var world = {
method1: function() {},
method2: function() {}
};
Para evitar que meu código polua o namespace global, tenho um processo de construção que envolve meus módulos em um encerramento e exporta a API pública para o namespace.Esta técnica também é usada pelo jQuery.Você pode ver isso em seu código-fonte (veja intro.js e outro.js) em GitHub.
Isso permitiria que você usasse um padrão que permite que seu IDE (ou ctags com vim) veja sua API, ao mesmo tempo que evita a poluição do namespace global.
Eu escrevo minhas bibliotecas como esta:
function MyLibrary() {
// code
}
MyLibrary.prototype.memberFunc = function() {
// code
}
MyLibrary.prototype.memberVar = 5;
new MyLibrary();
Dessa forma, em Geany (que usa CTAGs) MyLibrary
é bem reconhecido (na maioria das vezes, por exemplo, o membro é reconhecido como uma função) e a conclusão automática parece funcionar. Eu não sei sobre o Idea9, mas você pode tentar dessa maneira (eu tenho um palpite, é um pouco mais evoluído que o CTAGS).
Eu recomendo que você não use variáveis privadas, mas entendo que você deseja que elas sejam ocultadas do intellisense.É assim que eu faria:
(function(){
var privateVar = "shhhh!";
var privateMethod = function(){}
myLibray = {
prop:42,
foo: function(){
return privateMethod()
},
bar: function(){
return privateVar;
}
}
})();
Dessa forma, você pode ter suas coisas privadas fechadas e sua biblioteca deve estar acessível.
[editado.Desajeitadamente, não incluí myLibrary na função anônima e ela não conseguiu ver os vars privados.opa.]
Aliás, minhas razões para variáveis privadas serem ruins: http://clubajax.org/javascript-private-variables-are-evil/