2011-08-22 2 views
2

Cela peut sembler un peu inhabituel, je n'ai jamais eu besoin d'utiliser la notation en carré de cette façon avant, et en me creusant la tête, je n'arrive pas à trouver le moyen de produire le résultat souhaité.Javascript Notation du support carré Propriétés dynamiques multiples

Je suis mise en œuvre d'une enveloppe de rappel pour maintenir la référence de this lors du passage des méthodes comme callbacks

par exemple

foo.prototype.wrap = function(name){ 
    var wrapper, 
     self = this; 

    wrapper = function(){ 
     self[name](arguments); 
    }; 

    return wrapper; 
}; 

// usage 

foo.wrap('bar'); 

// executes foo.bar maintaining 'this' as a reference to foo 

La question que je vais avoir est que foo a des méthodes imbriquées

par exemple

foo.bar.close(); 

J'essaie de trouver un moyen de rendre le support de la méthode d'emballage des méthodes imbriquées

par exemple

foo.wrap('bar.close') 

// or 

foo.wrap('bar','close'); 

Ainsi, la fonction foo.wrap aurait besoin d'ajouter dynamiquement les crochets correspondant à la longueur ou les arguments transmis.

par exemple

self[x][y][z](arguments); 

Je ne trouve pas de moyen de le faire. Des idées ?

J'ai des soupçons, mais ce n'est pas possible.

Répondre

5

Je dois avoir un de ces jours où on oublie tout :)

Alors que @ la réponse de NilColor est correcte, et je ne sais que ce que je viens ne pensais pas avec le chapeau correct sur.

De toute façon, j'ai décidé que j'aime toujours l'idée d'avoir un emballage qui nécessite un peu moins de spécificité lorsque vous l'attachez à vos objets. Et est un peu moins verbeux.

Donc, je l'ai écrit avec ma ligne de pensée originale, vous pourriez l'aimer.

myObj.wrap = function(path, context){ 
    var wrapper, 
     method = (typeof path != 'string' && context)? path : this, 
     context = (typeof path === 'object' && context === undefined)? 
      path : (context || this); 

    if (typeof path === 'string'){ 
     path = path.split('.'); 

     for (var i = 0; i < path.length; i++){ 
      method = method[path[i]]; 
      if (context === true ) 
       context = (i === path.length - 2)? method : context; 
     }; 
    }; 

    wrapper = function(){ 
     method.apply(context, arguments); 
    }; 

    return wrapper; 
} 

usage:

lier un certain nombre de méthodes imbriquées pour myObj

myObj.wrap('foo') //binds myObj.foo to myObj 

// or 

    myObj.wrap('foo.bar') //binds myObj.foo.bar to myObj 

//or if myObj is a function 

    myFunc.wrap() // binds myFunc to myFunc 

Bind un procédé de myObj à un autre objet

myObj.wrap('foo.bar', someObj) //binds myObj.foo.bar to someObj 

//or if myObj is a function 

    myFunc.wrap(someObj) //Binds myFunc to someObj 

Bind une méthode imbriquée à son parent

myObj.wrap('foo.bar', true) // binds myObj.foo.bar to myObj.foo 

utilisation comme aide

myObj.wrap(someFunc, someObj) //binds someFunc to someObj 

Si vous cherchez une réponse à la question initiale non dans le contexte de la méthode de liaison.

myObj.getProps = function(path, context){ 
var context = context || this; 
    path = path.split('.'); 


for (var i = 0; i < path.length; i++){ 
      context = context[path[i]]; 
    }; 

    return context; 
}; 

Utilisation:

joindrez à un objet ou en fonction autonome

obtenir les propriétés

myObj.getProps('foo.bar') // returns mayObj.foo.bar 

Donnez-lui un objet de contexte

myObj.getProps('user.name', myAccounts) // returns myAccounts.user.name 

pour l'utiliser en fonction autonome remplacer

myObj.getProps = function(path,context){....} 

avec

function getProps(path,context){....} 

Remarque

Si vous utilisez comme fonction autonome, vous aurez besoin de se rappeler qu'il va commencer à la recherche de la portée de this. Donc, s'il est défini dans la portée globale, vous devez fournir des chemins complets.

par exemple.

getProps('myObj.foo.bar') 

Vous pouvez toujours utiliser le sélecteur de contexte pour modifier l'objet de référence.

+0

+ 1 Réponse brillante. Devrait avoir plus de upVotes. – User2

3

Un concept général de "liant" this est quelque chose comme ceci:

function bind(method, context) { 
     var args = Array.prototype.slice.call(arguments, 2); 
     return function() { 
      var a = args.concat(
           Array.prototype.slice.call(arguments, 0)); 
      return method.apply(context, a); 
     } 
} 

De cette façon, vous obtiendrez une référence à method avec this lié (context). De cette façon, vous pouvez lier les méthodes imbriquées comme ceci:

> foo = {} 
> foo.a = function(){console.log('a'); console.log(this)} 
> bar = {bar: 'yeah'} 
> f = bind(foo.a, bar) 
> f() 
-> a 
-> {bar: 'yeah', __proto__: Object} 

Est-ce que vous cherchez quelque chose?

+0

Cela fonctionne très bien merci. – AshHeskes

+0

désolé j'ai décoché votre réponse, pas parce que c'était faux, mais parce que j'ai répondu à ma question ci-dessus avec plus de précision. – AshHeskes

+0

Cela vous aide. C'est bon. Je ne sais pas pourquoi vous l'avez décoché ... Quoi qu'il en soit, bonne chance. – NilColor

Questions connexes