新手模拟实现 call 和 apply
发布于: 2021 年 06 月 06 日
其实面试中问的知识点都是希望你能讲使用场景,或者原理,因为只有知道什么时候用,用的时候会发生什么,这才能算得上是对这个知识点的理解嘛。
那下面就来看看它们的使用场景,以及实现方式。
使用场景 call 和 apply
求最大值和最小值
var numbers = [1, 20, 3, 40 ,60];
Math.max.apply(Math, numbers); // 60
Math.min.apply(Math, numbers); // 1
Math.max.call(Math, ...numbers); // 60
Math.min.call(Math, ...numbers); // 1
复制代码
合并数组
var arr1 = [1, 2];
var arr2 = [3, 4];
将第二个数组合并到第一个数组
Array.prototype.push.apply(arr1,arr2); // 4
console.log(arr1); // [1, 2, 3, 4]
复制代码
验证是否是数组
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
var number = isArray(1); // false
var obj = isArray({a:1}); // false
var string = isArray('1'); // false
var boolean = isArray(true); // false
var array = isArray([1]); // true
复制代码
调用父构造函数实现继承
function Person(name, age){
this.name = name;
this.age = age;
}
function Jack(name, age){
Person.call(this, name, age);
}
function Peter(name, age){
Person.call(this, name, age);
}
var jack = new Jack('jack', 18); // {name:'jack', age:18}
var peter = new Peter('peter',18); // {name:'peter', age:18}
通过父函数调用call,使得上面两个构造函数创建的实例都拥有父函数的属性,从而实现继承。
复制代码
模拟实现
call
我们先描述一下call是用来做什么的, 能得到什么
1. 传入多个参数,第一个参数为需要改变的this指向不传时候指向window
2. 改变this指向
3. 会执行调用call的函数,且能传入参数
4. 返回调用call的函数的执行结果
Function.prototype.myCall = function (context, ...args) {
// 判断第一个参数,为null或Undefined时this指向为Window,Object(context)是因为this参数可以传入基 本数据类型,原生call会自动用Object()转换
context = context ? Object(context) : Window;
// 改变this指向
context.fn = this;
// 执行函数,传入参数(这里是es6的数组解构)
let result = context.fn(...args);
// 函数执行完毕删除属性
delete context.fn;
// 返回函数执行的结果
return result;
};
用上面的例子来试试:
function Person(name, age){
this.name = name;
this.age = age;
}
function Jack(name, age){
Person.myCall(this, name,age);
}
function Peter(name, age){
Person.myCall(this, name, age);
}
var jack = new Jack('jack1', 18); // {name:'jack1', age:18}
var peter = new Peter('peter2',18); // {name:'peter2', age:18}
--------------------------------------------------------------------
function isArray(obj) {
return Object.prototype.toString.myCall(obj) === '[object Array]';
}
var number = isArray(1); // false
var obj = isArray({a:1}); // false
var string = isArray('1'); // false
var boolean = isArray(true); // false
var array = isArray([1]); // true
复制代码
apply
apply的实现其实就是将接收的参数修改一下即可
Function.prototype.myApply = function (context, args) {
// 判断第一个参数,为null或Undefined时this指向为Window,Object(context)是因为this参数可以传入基 本数据类型,原生apply会自动用Object()转换
context = context ? Object(context) : Window;
// 改变this指向
context.fn = this;
// 执行函数,传入参数(这里是es6的数组解构)
let result = context.fn(...args);
// 函数执行完毕删除属性
delete context.fn;
// 返回函数执行的结果
return result;
};
用上面的例子来试试:
var arr1 = [1, 2];
var arr2 = [3, 4];
将第二个数组合并到第一个数组
Array.prototype.push.myApply(arr1,arr2); // 4
console.log(arr1); // [1, 2, 3, 4]
-----------------------------------------------------
var numbers = [1, 20, 3, 40 ,60];
Math.max.myApply(Math, numbers); // 60
Math.min.myApply(Math, numbers); // 1
复制代码
划线
评论
复制
发布于: 2021 年 06 月 06 日阅读数: 17
版权声明: 本文为 InfoQ 作者【前端树洞】的原创文章。
原文链接:【http://xie.infoq.cn/article/cfe671c3f2ad94436a2595886】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
前端树洞
关注
还未添加个人签名 2020.07.16 加入
不仅能倾听,还能分解,前端,面试,nodeJS,源码都有,公众号同名(前端树洞)
评论