首先在模擬實現前,先Mark一些我以前不知道的知識:數組
其中,string是必需傳入的待計算或待執行的語句,而且必須是原始字符串的形式!app
eval(string)至關於<script> string </script>函數
類數組對象是一個對象,好比:arguments、DOM API返回的NodeList對象都屬於類數組對象,具備指向對象元素的數組index下標和length屬性,可是它們不能使用push/pop/shift/unshift等數組方法!測試
可是如何能將類數組轉換爲真正的數組呢?有以下方法:this
如下例爲例演示:spa
var foo = { value: 1 }; function bar(name, age) { console.log(this.value);
console.log(name)
console.log(age) } bar.call(foo, 'ning', 20);
這裏能夠考慮將bar這個函數做爲foo的一個方法,而後在外層執行這個函數,而後再刪掉該函數便可!prototype
Function.prototype.call2 = function (context) { context.fn = this; // context是foo,this是bar也就是調用call的那個函數 context.fn(); delete context.fn; } // 使用下例來驗證call2是否可行 var foo = { value: 1 } function bar() { console.log(this.value); } bar.call2(foo);
content.fn = this;這句首先獲取到了調用call的函數,本例這裏也就是bar;code
context.fn();即執行bar這個函數;對象
delete刪掉該函數。blog
可是如今的模擬中有幾個問題:
因此咱們獲得如下call2()代碼:
Function.prototype.call2 = function (context) { context = context ? Object(context) : window; context.fn = this; var arr = []; for (var i = 1, len = arguments.length; i < len; i++) { arr.push('arguments[' + i + ']'); } var result = eval('context.fn(' + arr + ')'); delete context.fn; return result; }
下面咱們測試一下:
var value = 'global'; var foo = { value: 1 } function bar(name, age) { console.log(this.value) return { value: this.value, name: name, age: age } } bar.call2(null) // global console.log(bar.call2(foo, 'ning', 20)) // 1 // {value: 1, name: "ning", age: 20}
說明兩點:
下面給出ES6版本的:
Function.prototype.call2 = function (context) { context = context ? Object(context) : window; context.fn = this; let arr = [...arguments].slice(1); let result = context.fn(' + arr + '); delete context.fn; return result; }
Function.prototype.apply2 = function (context, arr) { context = context ? Object(context) : window; context.fn = this; var result = []; // 沒有arr參數直接執行 if (!arr) { result = context.fn(); // 有arr參數則將參數拼接後執行 } else { var args = []; for (var i = 0; i < arr.length; i++) { args.push('arr[' + i + ']') } result = eval('context.fn(' + args + ')') } delete context.fn; return result; }
下面給出ES6版本的:
Function.prototype.apply2 = function (context, arr) { context = context ? Object(context) : window; context.fn = this; let result = []; if (!arr) { result = context.fn(); } else { // ...arr的使用 result = context.fn(...arr) } delete context.fn; return result; }