首頁  >  問答  >  主體

javascript - js中call方法的實現

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;
}

是為了模擬call的實現,請問為什麼要push一個字串,下面再用eval?直接傳入arguments[i],然後下面用context.fn(args)為什麼不行?

PHP中文网PHP中文网2685 天前823

全部回覆(3)我來回復

  • 给我你的怀抱

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

    這裡我相信你也已經明白了call的原理,這裡我簡要還是說明一下原理,我也是參考JavaScript權威指南的說明然後用代碼實現的。

    首先我們來看看call的語法和定義,來自ECMAScript規範中文版:

    還是簡單舉個栗子:

    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

    然後看看使用call之後的輸出:

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

    下面我結合栗子來解答你的疑問:

    是為了模擬call的實現,請問為什麼要push一個字串,下面再用eval?直接傳入arguments[i],然後下面用context.fn(args)為什麼不行?

    首先你要明白上面模擬的函數對應栗子中變數的關係:

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

    注意到這一步,我們只是把 jawil.sayHello的引用地址給了lulin.sayHello

    原來 jawil.sayHello.call(context,arg1,arg2,arg3,arg4)

    照你的方式剔除context得到args=[arg1,arg2,arg3,arg4]

    然後執行lulin.sayHello([arg1,arg2,arg3,arg4])哈哈,很有迷惑性是不是,看著沒問題,其實已經變味了,原來是原來是四個參數,現在集合到一個陣列就是一個陣列參數了,問題就出在這裡。

    那麼怎麼解決這個問題,思路就是上面那樣,把所有參數拼成字串,然後用eval執行。

    我們想要的效果是lulin.sayHello(arg1,arg2,arg3,arg4)這樣的,因為lulin.sayHello要重組參數,你不能拿到一個參數執行一次函數把吧,或把參數存到一起一次執行吧,唯一的想到的做法就是把所有參數拼成字串,然後用eval執行,

    類似這種:「lulin.sayHello(arg1,arg2,arg3,arg4)」這才是我們想要的方式,而不是lulin.sayHello([arg1,arg2,arg3,arg4]),也不是 lulin.sayHello(arg1),lulin.sayHello(arg2)...

    什麼是eval,這裡也簡單說一下,我就當你什麼都不知道。

    先簡單了解一下eval函數吧
    定義和用法

    eval() 函數可計算某個字串,並執行其中的 JavaScript 程式碼。

    語法:
    eval(string)

    string必需。要計算的字串,其中包含要計算的 JavaScript 表達式或要執行的語句。此方法只接受原始字串作為參數,如果 string 參數不是原始字串,那麼該方法將不作任何改變地傳回。因此請不要為 eval() 函數傳遞 String 物件作為參數。

    簡單來說吧,就是用JavaScript的解析引擎來解析這一堆字串裡面的內容,這麼說吧,你可以這麼理解,你把eval看成是