經常能使用到call和apply的情況下進行內部實現
<script>
//ES6版
Function.prototype.newCall = function (obj) {
//判斷參數傳入的值是否爲null或者undefined
obj = obj ? Object(obj) : window;
//this指向設置爲調用對象
obj.func = this;
//截取參數數組中除了元對象外的參數列表
let args = [...arguments].slice(1);
//當前保存有this指向和參數內容的變量
let res = obj.func(...args);
//刪除該函數
delete obj.func
//返回上下文
return res;
}
//ES5
Function.prototype.newCall = function (obj) {
obj = obj ? Object(obj) : window;
obj.func = this;
var args = [];
//爲取代擴展運算符使用手動分割數組爲參數列表
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
//args 會自動調用 args.toString() 方法
var result = eval('context.func(' + args + ')');
delete obj.func
return result;
}
//ES6版
Function.prototype.newApply = function (context, arr) {
//判斷參數傳入的值是否爲null或者undefined
context = context ? Object(context) : window;
//this指向設置爲調用對象
context.fn = this;
//當前保存有this指向和參數內容的變量
let result;
// 判斷是否存在第二個參數
if (!arr) {
result = context.fn();
} else {
//數組參數合併爲一個參數列表
result = context.fn(...arr);
}
//刪除該函數
delete context.fn
//返回上下文
return result;
}
//ES5
Function.prototype.newApply = function (context, arr) {
context = context ? Object(context) : window;
context.fn = this;
var result;
// 判斷是否存在第二個參數
if (!arr) {
result = context.fn();
} else {
//更改傳參方法
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')');
}
delete context.fn
return result;
}
</script>