Maison  >  Questions et réponses  >  le corps du texte

javascript - Implémentation d'une méthode d'appel en js

Function.prototype.call2 = function(context) {
    context.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    eval('context.fn(' + args +')');
    delete context.fn;
}

Il s'agit de simuler l'implémentation de call. Pourquoi avez-vous besoin de pousser une chaîne puis d'utiliser eval ensuite ? Pourquoi ne pas transmettre directement arguments[i] puis utiliser context.fn(args) ?

PHP中文网PHP中文网2685 Il y a quelques jours821

répondre à tous(3)je répondrai

  • 给我你的怀抱

    给我你的怀抱2017-06-12 09:32:07

    Ici, je pense que vous avez également compris les instructions du call的原理,这里我简要还是说明一下原理,我也是参考JavaScriptguide faisant autorité et que vous l'avez ensuite implémenté avec du code.

    Tout d'abord, jetons un coup d'œil à la syntaxe et à la définition de call, à partir de la version chinoise de la spécification ECMAScript :

    Donnons un exemple simple :

    var jawil = {
        name: "jawil",
        sayHello: function (age) {
             console.log("hello, i am ", this.name + " " + age + " years old");
         }
    };
    
    var  lulin = {
        name: "lulin",
    };
    
    jawil.sayHello(24);
    
    // hello, i am jawil 24 years old

    Ensuite, regardez le résultat après avoir utilisé call :

    jawil.sayHello.call(lulin, 24);// hello, i am lulin 24 years old
    

    Laissez-moi répondre à vos questions à base de marrons :

    consiste à simuler l'implémentation de call的实现,请问为什么要push一个字符串,下面再用eval?直接传入arguments[i],然后下面用context.fn(args) Pourquoi avez-vous besoin de pousser une chaîne et d'utiliser eval ensuite ? Transmettez directement arguments[i], puis utilisez context.fn(args) pourquoi pas ?

    Tout d'abord, vous devez comprendre la relation entre les fonctions simulées ci-dessus et les variables dans le châtaignier :

    context  => lulin
    
    context.fn => jawil.sayHello

    Remarquez cette étape, on vient de mettre jawil.sayHello的引用地址给了lulin.sayHello

    Il s'avère jawil.sayHello.call(context,arg1,arg2,arg3,arg4)

    Cull à votre façoncontext得到args=[arg1,arg2,arg3,arg4]

    Ensuite, exécutez lulin.sayHello([arg1,arg2,arg3,arg4])Haha, c'est très déroutant, n'est-ce pas ? Cela a l'air bien, mais en fait, il s'avère qu'il y avait quatre paramètres, et maintenant ils sont regroupés dans un tableau et deviennent un seul paramètre de tableau. C'est là que réside le problème.

    Alors, comment résoudre ce problème ? L'idée est la même que ci-dessus, mettre tous les paramètres dans une chaîne, puis utiliser eval pour exécuter.

    L'effet que nous voulons est lulin.sayHello(arg1,arg2,arg3,arg4), car lulin.sayHello doit réorganiser les paramètres, vous ne pouvez pas lulin.sayHello(arg1,arg2,arg3,arg4)这样的,因为lulin.sayHello要重组参数,你不能拿到一个参数执行一次函数吧,或者把参数存到一起一次执行吧,唯一的想到的做法就是把所有参数拼成字符串,然后用evalen obtenir un Exécutez la fonction une fois avec les paramètres

    , ou

    enregistrez les paramètres ensemble et exécutez-la une fois lulin.sayHello([arg1,arg2,arg3,arg4]),也不是lulin.sayHello(arg1),lulin.sayHello(arg2) La seule façon qui me vient à l'esprit est de mettre tous les paramètres dans une chaîne, puis d'utiliser

    pour exécuter,

    .

    Similaire à ceci : "lulin.sayHello(arg1,arg2,arg3,arg4)" C'est comme ça que nous voulons, pas

    , ni lulin.sayHello(arg1),lulin.sayHello (arg2)...eval
    Qu'est-ce qu'eval ? Laissez-moi vous l'expliquer brièvement ici. Je ferai comme si vous ne saviez rien.

    Jetons un bref aperçu de la

    fonction

    définition et utilisation
    La fonction


    eval() peut calculer une chaîne et y exécuter le code JavaScript. eval(string)

    Grammaire :

    🎜 🎜🎜chaîne requise. Chaîne à évaluer qui contient une expression JavaScript à évaluer ou une instruction à exécuter. Cette méthode n'accepte qu'une chaîne brute comme paramètre, si le paramètre de chaîne n'est pas une chaîne brute, alors la méthode retournera inchangée. Par conséquent, veuillez ne pas transmettre d'objets String comme arguments à la fonction eval(). 🎜

    Pour faire simple, il utilise le moteur d'analyse JavaScript pour analyser le contenu de ce groupe de chaînes. Disons-le de cette façon, vous pouvez le comprendre de cette façon, vous mettez la balise eval看成是<script>.

    eval('function Test(a,b,c,d){console.log(a,b,c,d)};
    Test(1,2,3,4)')

    C'est équivalent à ça

    <script>
    function Test(a,b,c,d){
    console.log(a,b,c,d)
    };
    Test(1,2,3,4)
    </script>

    D'accord, regardons à nouveau le code ci-dessus. En fait, il y a encore des pièges. Jetons un coup d'œil à l'intuition modale. Ci-dessous le code de débogage complet :

    Function.prototype.call2 = function(context) {
        context.fn = this;
        var args = [];
        for (var i = 1, len = arguments.length; i < len; i++) {
            args.push('arguments[' + i + ']');
        }
    
        console.log(args)
    
        var star = 'context.fn(' + args + ')'
    
        console.log(star)
        
        eval('context.fn(' + args + ')');
    
        delete context.fn;
    }
    
    
    var jawil = {
        name: "jawil",
        sayHello: function(age) {
            console.log("hello, i am ", this.name + " " + age + " years old");
        }
    };
    
    var lulin = {
        name: "lulin",
    };
    
    
    jawil.sayHello.call2(lulin, 24, 25);
    

    Regardez le résultat d'args :

    ["arguments[1]", "arguments[2]"]

    Regardez ensuite le résultat de 'context.fn(' + args + ')' :

    "context.fn(arguments[1],arguments[2])"N'est-ce pas un peu déroutant

    En fait, il s'agit ici d'une conversion implicite.

    'jawil'+[1,2]+[3,4]+3 équivaut à quoi ?

    Égal à "jawil1,23,43"'jawil'+[1,2]+[3,4]+3等于多少?
    等于"jawil1,23,43"
    其实这个相当于'jawil'+[1,2].toString()+[3,4].toString()+3En fait, cela équivaut à 'jawil'+[1,2].toString()+[3,4].toString( )+3< /code>

    L'espace est limité, pour plus de conversions implicites, veuillez vous référer à mon article : From ++[[]][+[]]+[+[]]==10 ? JS

    En parlant de cela, j'ai dit toutes les choses essentielles. Vous pouvez le comprendre vous-même. L'auteur original a probablement consulté d'autres lors de l'écriture de ceci. Il y a beaucoup de choses qui n'ont pas été expliquées clairement, je suppose, en raison de l'espace limité, je viens de le mentionner. d'un seul coup. Cela semble être un paragraphe très court. Le code contient en fait beaucoup de points de connaissance.

    répondre
    0
  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-06-12 09:32:07

    args est un tableau, context.fn(args) n'a qu'un seul paramètre. Dans des circonstances normales, vous pouvez utiliser apply pour convertir le tableau en paramètres, mais ici, pour simuler un appel, utiliser apply n'a aucun sens. Il utilise donc le toString() du tableau pour déplacer des paramètres autres que le contexte vers context.fn.

    répondre
    0
  • 淡淡烟草味

    淡淡烟草味2017-06-12 09:32:07

    Parce que les arguments[0] sont le contexte
    N'avez-vous pas vu que la variable de boucle commence à 1 ?

    répondre
    0
  • Annulerrépondre