首先在模拟实现前,先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; }