4
votes

comment obtenir un objet d'une fermeture?

Comment obtenir un objet à partir d'une fermeture, c'est une confusion avec moi, voici la question:

var o = function () {
   var person = {
       name: 'jonathan',
       age: 24
   }
   return {
       run: function (key) {
           return person[key]
       }
   } 
}

question: Comment puis-je obtenir l'original personne sans changer le code source.


4 commentaires

objet de la personne ou nom de la personne ou âge de la personne?


{name: o (). run ("name"), age: to (). run ("age")}


Double possible de Accès aux variables piégées par fermeture


Vous ne pouvez pas


5 Réponses :


2
votes

Vous pouvez obtenir les clés en exécutant

var o = function () {
   var person = {
       name: 'jonathan',
       age: 24
   }
   return {
       run: function (key) {
           return person[key]
       }
   } 
}

console.log(o().run("name"));
console.log(o().run("age"));

Comme ça:

o().run("<keyname>"))


11 commentaires

Cela n'a pas de sens si vous ne connaissez pas les noms des propriétés.


@NisargShah Je peux regarder le code et voir les noms de propriétés, ou peut-être qu'ils sont documentés ... lol


@NisargShah Autant que je sache, il serait impossible de renvoyer l'objet entier de la personne sans changer le code. Et comme OP a dit que c'était une question d'entrevue, je pense que c'est ainsi qu'il était censé le faire.


@epascarello Je suis presque sûr que l'intervieweur n'attend pas cette réponse. :) La réponse attendue serait "Vous ne pouvez pas".


@JonasWilms Jup, vient de voir votre réponse. Je n'en étais pas conscient. +1 de moi! :)


J'avais l'habitude de donner des interviews ... J'attends n'importe quelle réponse ... mieux que pas de réponse. Et puisque l'intervieweur n'est pas là, nous ne pouvons que DEVINER ce qu'ils recherchaient.


@epascarello par curiosité - préféreriez-vous une réponse de "ça ne peut pas être fait" ou ce que Jonas Wilms a fait? Parce que j'ai aussi donné des interviews (pendant une courte période) et personnellement je ne peux pas dire si l'un des deux est préférable parce que je ne poserais même pas la question. Pas dans sa forme actuelle, du moins - je poserais une question plus générale sur les fermetures.


@VLAZ était d'accord. Être un bon développeur ne signifie pas que vous devez savoir comment casser du code construit. J'ai récemment eu une super interview, et nous n'avons pas du tout parlé de code.


Les trois réponses «ne peut pas», «lire les accessoires» et «définir / évaluer» montrent toutes le concept de base selon lequel ils savent que la personne n'est pas accessible directement. Pour non, je continuerais avec une autre réponse sur la façon dont vous pouvez "recréer" avec la méthode disponible. Pour la méthode un, j'aurais suivi avec pourquoi vous ne pouvez pas obtenir «personne» directement juste pour que j'entende les mots que je pense qu'ils savent. Et pour l'autre ... ce type est fou.


Cette question signifie obtenir l'objet original person dans cette fonction o , donc ce n'est pas ce que vous pensez.


@ 芝 华 塔尼欧 Eh bien, vous avez commenté à la réponse de JonasWilms, que vous ne voulez pas changer, ni ajouter de code. Mon approche utilise le code fourni mais n'ajoute aucune fonctionnalité. Comme JonasWilms l'a suggéré, le seul moyen de contourner est d'utiliser un débogueur.



1
votes

Pourrait simplement toString la fonction, extraire la partie dont vous avez besoin et l'évaluer pour l'obtenir en tant qu'objet. Ceci est assez fragile, donc le faire fonctionner dans différents cas peut être difficile.

var o = function () {
   var person = {
       name: 'jonathan',
       age: 24
   }
   return {
       run: function (key) {
           return person[key]
       }
   } 
}

var person = eval('(' + o.toString().substr(30, 46) + ')')

console.log(person)


5 commentaires

Clause de non-responsabilité, c'est un hack super laid et son utilisation dans le code de production n'est pas recommandée. Cela pourrait avoir des effets néfastes sur votre santé. De vos collègues qui vous frappent.


Je veux dire, c'est terrible, mais cela montre que vous pouvez sortir des sentiers battus. Certainement pas quelque chose que j'utiliserais en production. : P


Pour être honnête, cette question d'entrevue est plutôt mauvaise. Alors, comme on dit - posez des questions stupides, obtenez des réponses stupides.


Exactement. Dans quelle situation auriez-vous besoin de l'obtenir sans pouvoir changer le code source? Vous ne devriez jamais avoir besoin d'accéder à quelque chose qui se trouve dans une fermeture depuis l'extérieur.


vous savez quoi - j'ai en fait pensé à une bonne raison. Eh bien, pas le meilleur, pour être honnête - c'est encore relativement mauvais tout bien considéré, mais c'est parti - les tests. Si vous souhaitez créer un espion à des fins de test unitaire, vous devrez peut-être "pénétrer" une fermeture. Il est toujours préférable 1. d'utiliser une bibliothèque dédiée 2. d'écrire du code testable unitaire, cependant, c'est encore une raison plus légitime à laquelle je peux penser. Tout le reste est lié à une mauvaise architecture, une mauvaise conception, un mauvais codage ou plusieurs d'entre eux.



10
votes

var o = function() {
  var person = {
    name: 'jonathan',
    age: 24
  }
  return {
    run: function(key) {
      return person[key]
    }
  }
}

Object.defineProperty(Object.prototype, "self", {
  get() {
    return this;
  }
});

console.log(o().run("self")); // logs the object

Cela fonctionne car tous les objets héritent du Object.prototype , vous pouvez donc y insérer un getter, qui a accès à l'objet via this , alors vous pouvez utiliser la méthode run exposée pour exécuter ce getter.


11 commentaires

Semble que je suis bon à questions d'entretien :)


@adiga cela dépend de la façon dont vous "code source". Si vous voulez simplement dire "ne changez pas le code qui définit la fermeture", c'est-à-dire ce qui est cité dans l'OP, alors la définition d'un getter fonctionne. Si cela signifie sans changer AUCUN code, alors ce n'est pas possible par définition car vous n'êtes pas autorisé à changer quoi que ce soit.


J'utiliserais un Symbol au lieu de "self" afin de ne casser aucun objet qui pourrait avoir "self" (ou tout autre key) défini.


(@VLAZ je n'étais pas sérieux)


@dmitry Je n'utiliserais pas du tout ce code. En réalité, personne n'aurait une fonction o qui renvoie les clés d'une personne? Il s'agit d'un code construit destiné à contester les entretiens.


@JonasWilms alors vous obtiendrez plus de points sur l'interview pour savoir ce que fait Symbol :)


C'est une bonne idée, mais je suis sûr que «sans changer le code source», la signification de cette phrase, s'il faut ou non l'ajouter. De plus, y a-t-il un autre moyen?


@ 芝 华 塔尼欧 Comment codez-vous sans écrire de code? Je le comprends comme "ne modifiez pas le code présenté, ajoutez du code" ... Si vous n'êtes pas du tout autorisé à coder, alors je répondrais: "Je vais au débogueur, place un point d'arrêt et regarde la portée" ou "Je sais que son nom est Jonathan, pourquoi devrais-je investir autant d'efforts juste pour découvrir l'évidence?" (Cela dit, c'est une question d'entretien horrible)


@ 芝 华 塔尼欧 si vous n'êtes pas autorisé à modifier AUCUN code source, cette tâche est impossible. Même si person a été exposé, vous ne pouvez pas écrire de code qui le prend car vous n'êtes pas autorisé à écrire de code. Si la limitation est de ne pas toucher la fermeture, alors le changement du prototype Object est techniquement valide. Vous n'y avez modifié aucun code. Vous venez de changer le fonctionnement de tous les objets dans votre base de code, c'est-à-dire comment les prototypes fonctionnent et comment ils sont supposés fonctionner. C'est juste une mauvaise pratique en général.


@JonasWilms Ouais, je ne sais vraiment pas, peut-être que tu as raison.


@VLAZ Oui, c'est vraiment une façon de changer le prototype de Object .



-2
votes

o (). run ("nom") Ce sera le retour "jonathan".


0 commentaires

-2
votes

Vous pouvez simplement créer ce

<script type="text/javascript">
 var o = function () {
  var person = {
   name: 'jonathan',
   age: 24
  }
  return {
   run: function (key) {
       return person[key]
   }
  } 
 }
let a = new o;
alert(a.run('name'));
</script>


0 commentaires