2010-10-12 12 views
9

He desarrollado un pequeño widget javscript para convertir algunos bloques anidados <ul> en un explorador de estilo de Windows Explorer. He aprendido recientemente sobre el modelo de objeto literal y decidió darle una oportunidad, por lo que la organización de mi código es algo como esto:javascript objeto patrón literal con varias instancias

var myExplorer = { 
    init : function(settings) { 
     myExplorer.config = { 
      $wrapper : $('#explorerCategories'), 
      $contentHolder : $j('#categoryContent'), 
      loadingImg : '<img src="../images/standard/misc/ajax_loader.gif" alt="loading" class="loading" />' 
     } 
     // provide for custom configuration via init() 
     if (settings && typeof(settings) == 'object') { 
      $.extend(myExplorer.config, settings); 
     } 

     // some more code... 
    }, 

    createExpanderLink : function() { 
     // more code 
    }, 

    anotherMethod : function() { 
     // etc 
    } 
} 

Luego, en mi página de configurar mi explorador con:

$j(function() { 
    myExplorer.init(); 
} 

Todo esto funciona bien por cierto. El problema es cuando quiero tener más de uno de estos widgets de estilo explorador en la misma página. He intentado pasar en las diferentes configuraciones:

$j(function() { 
    // first instance 
    myExplorer.init(); 

    //second instance 
    var settings = { 
     $wrapper : $('#explorerCategories2'), 
     $contentHolder : $j('#categoryContent2') 
    } 
    myExplorer.init(settings); 

} 

Pero esto simplemente sobrescribe los valles de configuración para la primera instancia que rompe eficazmente. Estoy empezando a darme cuenta de que el patrón literal del objeto no es el camino correcto, pero no estoy seguro de qué es. ¿Alguien puede ofrecer alguna sugerencia?

Respuesta

9

Utilice una función en su lugar en un objeto literal, para que pueda instanciar varios objetos del widget utilizando la palabra clave new.

function myExplorer(settings) { 
    // init code here, this refers to the current object 
    // we're not using a global object like myWindow anymore 
    this.config = { 
     $wrapper : $('#explorerCategories'), 
     $contentHolder : $j('#categoryContent'), 
     .. 
    }; 

    // provide for custom configuration 
    if (settings && typeof(settings) == 'object') { 
     $.extend(this.config, settings); 
    } 

    this.someFunction = function() { 
     .. 
    }; 

    this.otherFunction = function() { 

    }; 
} 

Instantate tantos objetos de este widget según sea necesario utilizando,

var foo = new myExplorer({ .. }); 
var bar = new myExplorer({ .. }); 
... 
+0

Perdone mi ignorancia, pero ¿es correcto que al usar este patrón debo declarar todas las funciones internas primero antes de usarlas dentro de la función circundante myExplorer? Me puse un poco confundido por tu código // init aquí comentario. – benb

2

Cuando se llama a $.extend() como este, que se fusiona las propiedades del segundo objeto en el primero:

$.extend(myExplorer.config, settings); 

su lugar, crear un nuevo objeto que es el resultado de la fusión que sale del primer objeto (los valores por defecto) sin tocar, como esto:

this.settings = $.extend({}, myExplorer.config, settings); 

lo que esto hace aún combinar los objetos pasados ​​a la primera, pero la primera es un objeto nuevo ({}), así que no estamos afectando cualquiera de las otras, entonces simplemente use this.settings (o un nombre diferente para dejarlo absolutamente claro) dentro de su objeto.

+0

Gracias. Probé esto pero no funcionó para mí. Mientras creaba un nuevo objeto de configuración dentro del objeto myExplorer, los valores seguían sobrescritos por la segunda llamada myExplorer.init (configuración). – benb

+0

@ben - Ni siquiera estaba mirando la estructura de tu objeto, solo tienes un solo objeto, necesitarás ir por una ruta completamente diferente para la creación de tu objeto usando lo anterior, la respuesta de Anurag es una posibilidad, hay muchos patrones aquí. –

8

¿Y esto?

 
var myExplorer = function(settings) { 

    var o = { 
    init: function() { 
     this.somevalue = settings; 
    }, 

    whatever: function() { 
    } 
    }; 

    o.init(); 

    return o; 
}; 

var exp1 = myExplorer('something'); 
var exp2 = myExplorer('anything'); 

console.log(exp1.somevalue); //something 
console.log(exp2.somevalue); //anything 
4

utilizar el siguiente código para lograr esto, recuerde acerca de la 'API pública' (de modo que la función 'interna' será visible 'fuera'):

var myExplorer = function() { 
    var init = function(settings) { 
     var config = { 
      $wrapper : $('#explorerCategories'), 
      $contentHolder : $j('#categoryContent'), 
      loadingImg : '<img src="../images/standard/misc/ajax_loader.gif" alt="loading" class="loading" />' 
     } 
     // provide for custom configuration via init() 
     if (settings && typeof(settings) == 'object') { 
      $.extend(config, settings); 
     } 

     // some more code... 
    }, 

    var createExpanderLink = function() { 
     // more code 
    }, 

    var anotherMethod = function() { 
     // etc 
    } 

    // Public API 
    // return the functions you want to use outside of the current instance 
    return { 
     init : init, 
     createExpanderLink : createExpanderLink, 
     anotherMethod : anotherMethod 
    } 
} 
var firstExplorer = new myExplorer(); 
var secondExplorer = new myExplorer(); 
// etc 
0

Desde mi entender está tratando de crear una nueva instancia de objeto que se definió utilizando la notación literal del objeto. literales de objetos se pueden crear instancias mediante el método Object.create. Aquí está el código que explica cómo crear una instancia de un objeto a partir de la notación literal del objeto.

  var objLiteral = { 
       name:"kanthan", 
       address:'', 
       deliver:function(){ 
        if(this.address){ 
         console.log("Your product has been successfully delivered at "+this.address); 
        } 
        else{ 
         console.log("please enter the address to deliver"); 
        } 
       } 
      }; 
      var cum=Object.create(objLiteral); 
      cum.address="gkm colony"; 
      objLiteral.deliver(); 
      cum.deliver(); 
      var cum1=objLiteral; 
      cum1.address="gkm colony"; 
      objLiteral.deliver(); 
      cum1.deliver(); 
Cuestiones relacionadas