一次关于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);