新手模拟实现call和apply

这是我参与更文挑战的第1天,活动详情查看: 更文挑战.

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

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

使用场景 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指向不传时候指向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


复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享