手写callapplybind函数和arguments&数组函数slice的实现
Posted 忘忘碎斌bin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写callapplybind函数和arguments&数组函数slice的实现相关的知识,希望对你有一定的参考价值。
手写call、apply、bind函数和arguments&数组函数slice的实现
手写call、apply、bind函数
手写call函数
Function.prototype.msicall = function (thisArg, ...args) {
//因为调用此方法是通过,函数对象调用的,那么这个函数内的this就是这个函数对象
var fn = this;
// 边界判断,系统call函数在调用的时候忽略显示绑定情况
thisArg =
thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
// 通过对象调用,使this绑定到传入要绑定的对象
thisArg.fn = fn;
// 调用函数,其实内部的this会存在fn这个函数,因为this指向的对像上是手动挂载上去的源函数
var result = thisArg.fn(...args);
// 删除挂载的函数
delete thisArg.fn;
// 返回值
return result;
};
手写apply函数
// 采用默认值,因为如果没有参数只有绑定对象,那么默认args就是undefined
// undefined在解构时会报错
Function.prototype.msiapply = function (thisArg, args = []) {
var fn = this;
thisArg =
thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
thisArg.fn = fn;
var result = thisArg.fn(...args);
delete thisArg.fn;
return result;
};
手写bind函数
Function.prototype.msibind = function (thisArg, ...args) {
var fn = this;
// edge case 边界判断
thisArg =
thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
return function (...params) {
thisArg.fn = fn;
// 系统bind在调用bind时可以传入部分参数,然后返回函数可以继续传入剩余参数
var allParams = [...args, ...params];
var result = thisArg.fn(...allParams);
delete thisArg.fn;
return result;
};
};
函数的arguments
介绍
arguments是一个伪数组,伪数组具有数组的一些特效,但是却不是一个数组,而是一个对象。
-
arguments会将函数调用时传入的参数全部放入其中
-
arguments可以和数组一样具有 length属性
-
arguments可以和函数一样通过下标访问内部数据
-
arguments具有callee属性,指向的是本函数
function foo(num1, num2) {
console.log(arguments.callee);
}
foo(10, 20, 30, 40);
// 打印
// ƒ foo(num1, num2) {
// console.log(arguments.callee);
// }
注意
:箭头函数内是不绑定arguments的,箭头函数内使用arguments,那么会把arguments当作一个变量来处理,会沿着作用域链来查找。
arguments在浏览器的全局作用域上是不存在的,但在node上是存在的,因为在node里每一个js文件都是放到一个函数内执行的(node源代码操作),这个函数上就有arguments,node内打印arguments的话,就是这个函数的arguments。
arguments转array
function foo(num1, num2) {
console.log(arguments); // Arguments(4) [10, 20, 30, 40, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// 1、 手动遍历转换
var newArray1 = [];
for (var i = 0; i < arguments.length; i++) {
// newArray1[i] = arguments[i];
newArray1.push(arguments[i]);
}
console.log(newArray1); // [10, 20, 30, 40]
// 2、数组方法转换 (也可以使用apply方法)
var newArray2 = Array.prototype.slice.call(arguments);
console.log(newArray2); // [10, 20, 30, 40]
var newArray3 = [].slice.call(arguments);
console.log(newArray3); // [10, 20, 30, 40]
// es6语法
var newArray4 = Array.from(arguments);
console.log(newArray4); // [10, 20, 30, 40]
var newArray5 = [...arguments];
console.log(newArray5); // [10, 20, 30, 40]
}
foo(10, 20, 30, 40);
知识补充:Array内slice方法的实现
之所以在arguments转array时方法二可以这样调用是因为内部是这样实现的:
Array.prototype.msislice = function (start, end) {
// 这里的this指向的是需要操作的数组
var array = this;
start = start || 0;
end = end || array.length;
var newArr = [];
for (var i = start; i < end; i++) {
newArr.push(array[i]);
}
console.log(newArr);
return newArr;
};
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].msislice();
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].msislice(5);
// [6, 7, 8, 9, 0]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].msislice(1, 5);
// [2, 3, 4, 5]
以上是关于手写callapplybind函数和arguments&数组函数slice的实现的主要内容,如果未能解决你的问题,请参考以下文章
手写JS面试题 --- call apply bind 实现