D'abord, je copie le contexte passé actuel dans dummy. Ensuite, j'ajoute une méthode fn en tant que fonction actuellement passée. L'objet factice existe dans la fermeture. Enfin, je retournerai une fonction qui exécute le dummy.fn avec les arguments initialement passés.

Function.prototype.bind2 = function(context, ...args){
    var dummy = {...context}
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

Edit 1: Après la première suggestion pour le nouvel objet factice, je l'ai changé comme suit

Function.prototype.bind2 = function(context, ...args){
    var dummy = Object.create(context)
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

Edit 2: pour le correctif de l'opérateur de propagation, j'ai utilisé eval:

Function.prototype.bind2 = function(){
    var args = arguments;
    var dummy = Object.create(args[0]);
    dummy.fn = this;
    return function(){
                return eval('dummy.fn('+Object.values(args).slice(1,).join(',')+')') 
           } 
}
1
kanine 17 févr. 2020 à 12:20

1 réponse

Meilleure réponse

Non, à première vue, il y a plusieurs problèmes :

  • bind invoquera la méthode sur le contexte passé, pas une copie de celui-ci - votre version rend impossible pour la fonction liée d'affecter directement le contexte

  • La méthode de copie d'un objet que vous utilisez coupera un objet de son prototype, ainsi que toute magie qu'il pourrait avoir

  • bind permettra également à la fonction d'accepter des paramètres supplémentaires qui ne sont pas liés

  • Tout environnement qui nécessiterait que bind soit polyrempli ne serait pas en mesure de gérer la syntaxe de propagation ....

Function.prototype.bind2 = function(context, ...args){
    var dummy = {...context}
    dummy.fn = this
    return function(){
        return dummy.fn(...args)
    }
}

let obj = Object.create({
  name: "an obj",
  getName: function() { return this.name; },
  setFoo: function() { this.foo = 42; },
  showBarBaz: function(bar, baz) { console.log(bar, baz) }
});
obj.setFoo.bind2(obj)();                 // does not set `obj.foo`
console.log(obj);
console.log(obj.getName.bind2(obj)());   // no access to prototype
obj.showBarBaz.bind2(obj, "bar")("baz"); // does not pass "baz"

obj.setFoo.bind(obj)();                  // sets `obj.foo`
console.log(obj);
console.log(obj.getName.bind(obj)());    // full access to prototype
obj.showBarBaz.bind(obj, "bar")("baz");  // passes "baz"
3
Amadan 17 févr. 2020 à 09:44