小明想要用數組的形式爲 Cls.func
傳入多個參數,他想到了如下的寫法:html
var a = new Cls.func.apply(null, [1, 2, 3]);
然而瀏覽器卻報錯 Cls.func.apply is not a constructor。
乍一看是 new 操做符去修飾 Cls.func.apply 了,因而他又這麼寫:git
var a = (new Cls.func).apply(null, [1, 2, 3]);
瀏覽器依舊報錯。。。好吧,仍是好好查一查相關的解決方法吧,還好這是個好時代,沒有什麼是網上查不出來的。github
在網上找到了很是關鍵的幾個解決方案和思路。數組
參考連接 http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible瀏覽器
關鍵摘抄:app
function newCall(Fn) { return new (Function.prototype.bind.apply(Fn, arguments)); // or even // return new (Fn.bind.apply(Fn, arguments)); // if you know that Fn.bind has not been overwritten } // It can be used as follows: var s = newCall(Fn, a, b, c); // or even directly: var a = new (Function.prototype.bind.call(Fn, null, 1, 2, 3)); var a = new (Function.prototype.bind.apply(Fn, [null, 1, 2, 3]));
以上關鍵就在於 .bind.apply() 或 .bind.call() 這中寫法。
Function.prototype.bind() 等同於 Fn.bind() 會建立一個新的函數,第一個參數爲新函數的 this 指向,然後多個參數爲綁定函數被調用時,這些參數將置於實參以前傳遞給被綁定的方法。函數
先分析一下 Function.prototype.bind.call() 這種寫法:this
var a = new (Function.prototype.bind.call(Fn, null, 1, 2, 3));
call() 接受多個參數,第一個參數爲函數執行的上下文環境,後面的參數會依次傳遞給前面的 bind 做爲參數。
因此 bind() 接到的參數爲 bind(null, 1, 2, 3)。因此上面的那種寫法就等同於:prototype
var a = new ( Fn.bind(null, 1, 2, 3)() );
同理再推導 Function.prototype.bind.apply() 寫法:code
var a = new (Function.prototype.bind.apply(Fn, [null, 1, 2, 3]);
call() 接受兩個參數,第一個參數爲函數執行的上下文環境,第二個參數爲數組,數組的每一項會一次做爲 bind() 的參數,所以 bind() 接受到的參數也爲 bind(null, 1, 2, 3)。所以也等價於:
var a = new ( Fn.bind(null, 1, 2, 3)() );
有了上面的推導,小明這時候就能夠輕易的寫出本身想要的結果了,同時爲了拓展方便,小明決定寫一個通用的方法:
function newApply(Fn, argsAry) { argsAry.unshift(null); return new (Fn.bind.apply(Fn, argsAry)); } // 調用 newApply(Cls.func, [1, 2, 3]) // well done !!
做者博客:pspgbhu http://www.cnblogs.com/pspgbhu/
原文連接:http://www.cnblogs.com/pspgbhu/p/6796795.html
做者GitHub:https://github.com/pspgbhu
歡迎轉載,但請註明出處,謝謝!