一次關於bug的自我否認

最近在學習JavaScript中的閉包,涉及到其中一個案例,想着改寫一下。案例挺簡單,可是改bug過程有些曲折,在此分享一下在改bug過程當中的自我懷疑自我否認直到曲徑通幽的心路歷程。
需求說明:咱們知道arguments對象若是想調用Array的push方法,須要使用Array.prototype.push.apply(argument,[1,2])這樣的方式,但每次都寫這麼一長串代碼特別繁瑣,想着提取一個push方法,方便之後直接調用。
廢話很少說,,直接貼代碼。node

//提取的方法
var push = (function(){
    return function(){
        var obj = Array.prototype.shift.apply(arguments);
        Array.prototype.push.apply(obj,arguments);
        return arguments;
    }
})()

方法洋洋灑灑寫完以後,進入自測階段。爲了偷懶,再次使用了自執行函數,代碼以下:git

//自測代碼
(function(){
    push(arguments,4)
    console.log(arguments);
})(1,2,3)

在node環境中執行,結果拋錯以下:github

Array.prototype.push.apply(obj,arguments);
                             ^

TypeError: Cannot assign to read only property 'length' of function 'function (){
    push(arguments,4)
    console.log(arguments);
}'

這個報錯很明顯,當給一個function調用Array.porotype.push方法時會拋出這樣的錯誤,由於一個function的length屬性是隻讀的,而push的源碼中length屬性是須要能夠修改的,即一個對象具備可讀寫的length屬性以後才能夠調用Array.porototype.push方法。
回到我提取的push方法中分析,Array.prototype.push.apply(obj,arguments);此刻個人obj應該是一個類數組{ '0': 1, '1': 2, '2': 3 },因此報錯提示沒法直觀解決問題。數組

首先爲了排除測試案例的緣由,我修改了個人測試案例,避免function的介入,代碼以下:
//測試案例
var fn = function(){
    push(arguments,4);
    console.log(arguments);
}
fn(1,2,3);

修改完成以後發現測試順利經過,說明我提取的方法沒有問題。到此,牽扯出了一個新問題,我使用自執行函數時爲啥會致使出錯。閉包

首先來到我腦海的緣由是自執行函數的執行順序,是否有異步一說。由於我提取push方法也是用的自執行函數,測試案例也是自執行函數,有可能兩自執行函數的前後執行順序致使了問題,爲了驗證這個答案,我決定將自測案例延時執行,代碼以下:
setTimeout(function(){
    (function(){
        push(arguments,4)
        console.log(arguments);
    })(1,2,3)
},10);

測試發現順利經過,這個測試結果更加懷疑了剛纔的假設(雖然內心一萬個不相信)。而後開始查js自執行函數的執行順序的問題,未果,說明你們都沒遇到這樣的問題,那頗有可能我這假設不對。沒辦法,只能繼續修改測試,既然是由於調用push.apply時候出錯,我先註釋掉它試試。代碼以下:app

//提取方法代碼
var push = (function(){
    return function(){
        var obj = Array.prototype.shift.apply(arguments);
        // Array.prototype.push.apply(obj,arguments);
        return arguments;
    }
})()
//測試案例代碼
(function(){
    // push(arguments,4)
    console.log(arguments);
})(1,2,3)

運行結果,拋出了不同的錯誤,不同的煙花,錯誤以下異步

D:\github\jsStudy\heightFn.js:174
    })(1,2,3)
      ^

TypeError: (intermediate value)(...)(...) is not a function

這個錯誤提示很容易定位到了問題,自執行函數結尾未寫分號致使。
這個問題實際上是一個小問題致使的,無關乎技巧。分享這個主要是想表達:在遇到問題時,咱們看到的問題可能只是表象,尋找解決方案的過程就是一個不斷自我猜測,驗證猜測,不斷否認的過程,須要持續不斷的挖掘。
最後貼出最終代碼:函數

var push = (function(){
    return function(){
        var obj = Array.prototype.shift.apply(arguments);
        Array.prototype.push.apply(obj,arguments);
        return arguments;
    }
})();
//測試案例
;(function(){
    push(arguments,4)
    console.log(arguments);
})(1,2,3);
相關文章
相關標籤/搜索