2009-10-21 5 views
38

J'ai lu que plutôt que d'écrire simplement un tas de fonctions, je devrais utiliser l'objet littéral. Est-ce que quelqu'un peut expliquer quels sont les avantages de l'objet littéral avec des exemples, parce que je ne comprends pas jusqu'à présent.JavaScript - Avantages de l'objet littéral

Merci

Répondre

64

Comme Russ Cam a dit, vous évitez de polluer l'espace de nommage global, ce qui est très important dans ces jours de combiner des scripts à partir de plusieurs endroits (TinyMCE, etc.). Comme l'a dit Alex Sexton, cela permet également une bonne organisation du code.

Si vous utilisez cette technique, je suggère d'utiliser le modèle de module. Celui-ci utilise encore littéraux d'objet, mais comme la valeur de retour d'une fonction de cadrage:

var MyThingy = (function() { 

    function doSomethingCool() { 
     ... 
    } 

    function internalSomething() { 
     .... 
    } 

    function anotherNiftyThing() { 
     // Note that within the scoping function, functions can 
     // call each other direct. 
     doSomethingCool(); 
     internalSomething(); 
    } 

    return { 
     doSomethingCool: doSomethingCool, 
     anotherNiftyThing: anotherNiftyThing 
    }; 
})(); 

Usage externe:

MyThingy.doSomethingCool(); 

La fonction de cadrage est enroulé autour de toutes vos fonctions, puis vous l'appelez immédiatement et stocker sa valeur de retour. Avantages:

  • Les fonctions sont normalement déclarées et ont donc noms. (Alors qu'avec le format {name: function() { ... }}, toutes vos fonctions sont anonymes, même si les propriétés qui les référencent ont des noms.) Les outils d'aide aux noms vous aident, depuis l'affichage des piles d'appels dans un débogueur jusqu'à la fonction qui déclenche une exception. (Mise à jour 2015: La dernière spécification JavaScript, ECMAScript 6ème édition, définit un grand nombre de façons dont le moteur JavaScript doit infer le nom d'une fonction, notamment lorsque la fonction est affectée à une propriété comme dans notre exemple {name: function() { ... }}. les moteurs implémentent ES6, cette raison disparaîtra.)
  • Vous donne la liberté d'avoir des fonctions privées utilisées uniquement par votre module (par exemple mon internalSomething ci-dessus). Aucun autre code sur la page ne peut appeler ces fonctions; ils sont vraiment privés. Seuls ceux que vous exportez à la fin, dans l'instruction return, sont visibles en dehors de la fonction de portée.
  • Facilite le retour de différentes fonctions en fonction de l'environnement, si l'implémentation change juste complètement (comme IE-vs-W3C, SVG ou Canvas, etc.).

Exemple de retour différentes fonctions:

var MyUtils = (function() { 
    function hookViaAttach(element, eventName, handler) { 
     element.attachEvent('on' + eventName, handler); 
    } 

    function hookViaListener(element, eventName, handler) { 
     element.addEventListener(eventName, handler, false); 
    } 

    return { 
     hook: window.attachEvent ? hookViaAttach : hookViaListener 
    }; 
})(); 

MyUtils.hook(document.getElementById('foo'), 'click', /* handler goes here */); 
+2

Lorsque vous instanciez une fonction de manière "anonyme", vous pouvez toujours lui donner un nom (var x = function x() {...}). Lorsque vous faites cela, le nom est lié de telle sorte qu'il est disponible pour les références récursives dans la fonction. – Pointy

+1

@Pointy: Vous ne pouvez pas faire cela (utiliser un nom de fonction dans une affectation) cross-browser, cela ne fonctionne pas correctement sur IE ou Safari; détails: http://yura.thinkweb2.com/named-function-expressions/ Et vous n'avez pas besoin, le nom propre de la fonction (le 'foo' dans' function foo') est dans le champ d'application dans toute la portée où il est déclaré, y compris dans la fonction elle-même, donc 'foo' peut s'appeler via le symbole' foo', pas besoin d'assigner la référence de la fonction à quelque chose (à ce moment-là). –

+0

(suite) Supposons qu'il serait * gentil * de pouvoir utiliser à la fois l'affectation et le nom propre en même temps, car cela faciliterait l'exportation des fonctions de la fonction de portée. La spécification le permet certes, mais malheureusement, les pratiques (bugs de mise en œuvre) y entrent. –

15

Utilisation d'un littéral objet (objet aka modèle littéral) ne pollueront pas l'espace de noms global aussi sévèrement que l'utilisation de nombreuses fonctions déclarées à l'échelle mondiale va, et contribue également à organiser le code d'une manière logique

Pour par exemple, cet objet littéral

var obj = { 
       find : function(elem) { /* find code */ }, 
       doSomething: function() { /* doSomething code */ }, 
       doSomethingElse: function() { /* doSomethingElse code */ } 
      } 

par rapport à

function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 

va créer une seule propriété sur l'objet global par rapport à trois. Vous pouvez ensuite utiliser facilement les fonctions comme si

obj.doSomething(); 
+2

vous pourriez juste écrire beaucoup de fonction dans une fonction normale et ne pas polluer votre code. l'objet littéral ne donne aucune valeur ajoutée. J'utilise moi-même la méthode du prototype .. – vsync

9

Rebecca Murphey a fait un exposé sur littéraux d'objet lors de la conférence de cette année jQuery. L'une des meilleures raisons de les utiliser est simplement une bonne organisation du code.

Voici l'écriture de Rebecca sur l'objet littérales Motif: http://rmurphey.com/blog/2009/10/15/using-objects-to-organize-your-code/

+2

Un autre grand article sur les littéraux d'objet: http://www.wait-till-i.com/2006/02/16/show-love-to-the-object-literal/ –

2

Ive toujours utilisé littéraux d'objet parce qu'ils sont une façon claire pour organiser le code. C'est pourquoi je n'aime pas les prototypes, c'est trop compliqué.

Les fonctions ne polarisent pas l'espace de nom en tant que personne mentionnée ci-dessus, pas plus que les littéraux d'objet.

Vous pouvez facilement écrire un littéral comme

var obj = {} 
var find = function(elem) { /* find code */ }, 
var doSomething = function() { /* doSomething code */ }, 
var doSomethingElse = function() { /* doSomethingElse code */ } 

qui en créant beaucoup polluer d'objets globaux même les mêmes que les fonctions. De même, vous pouvez faire:

(function() { 
function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 
})(); 

qui ne serait pas créer ces objets globaux (tout est un objet JS)

cette façon, vous ne créez pas encore les charges d'objets globaux.

À mon avis, les littéraux d'objets ont deux avantages. Un qu'ils sont utilisés par de nombreux plugins tels que jQuery afin que les gens sont familiers et ils sont faciles à lire. Les rendant faciles à passer à travers les données dans un plugin. Il est facile de créer des méthodes publiques et privées ....

Ils peuvent être lents, car chaque fois que vous créez une instance de l'objet, toutes ses méthodes sont dupliquées. Je crois comprendre que ce n'est pas le cas avec le prototype car vous avez une copie des méthodes et les nouveaux objets réfèrent simplement au prototype.

Je pourrais me tromper bien sûr ...

+1

Les littéraux d'objets sont utiles pour les espaces de noms et les singletons. Lorsque vous créez plusieurs instances d'un objet avec un comportement partagé, il est préférable d'utiliser les fonctions de constructeur. Je n'ai pas trouvé de cas d'utilisation où consommer plus de cpu et de mémoire en simulant des chemins privés en utilisant '_myPrivate' pour les privés à la place, mais je serais heureux si quelqu'un pouvait m'en fournir un. Plus sur le prototype, l'héritage, mélanger ins ici: http://stackoverflow.com/a/16063711/1641941 – HMR

Questions connexes