写点什么

新手模拟实现 call 和 apply

用户头像
前端树洞
关注
发布于: 2021 年 06 月 06 日

其实面试中问的知识点都是希望你能讲使用场景,或者原理,因为只有知道什么时候用,用的时候会发生什么,这才能算得上是对这个知识点的理解嘛。


那下面就来看看它们的使用场景,以及实现方式。

使用场景 call 和 apply
  1. 求最大值和最小值


   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
复制代码


  1. 合并数组


   var arr1 = [1, 2];   var arr2 = [3, 4];      将第二个数组合并到第一个数组   Array.prototype.push.apply(arr1,arr2); // 4   console.log(arr1); // [1, 2, 3, 4]
复制代码


  1. 验证是否是数组


   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
复制代码


  1. 调用父构造函数实现继承


   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指向不传时候指向window2. 改变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); // falsevar obj = isArray({a:1}); // falsevar string = isArray('1'); // falsevar boolean = isArray(true); // falsevar 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); // 4console.log(arr1); // [1, 2, 3, 4]
-----------------------------------------------------var numbers = [1, 20, 3, 40 ,60];
Math.max.myApply(Math, numbers); // 60Math.min.myApply(Math, numbers); // 1
复制代码


发布于: 2021 年 06 月 06 日阅读数: 17
用户头像

前端树洞

关注

还未添加个人签名 2020.07.16 加入

不仅能倾听,还能分解,前端,面试,nodeJS,源码都有,公众号同名(前端树洞)

评论

发布
暂无评论
新手模拟实现call和apply