call/ applay的作用及区别(手写实现)

本文详细介绍了JavaScript中call和apply方法的相同点与不同点,包括它们的作用、参数用法及示例。同时,文章展示了如何利用这两个方法实现函数的继承和一些特殊的使用场景,如改变Math.max的用法以及Array.prototype.push的应用。此外,还提供了call和apply的手写实现,帮助读者深入理解其工作原理。
摘要由CSDN通过智能技术生成

一、相同点

作用:都是用于改变this的指向。第一个参数为你要传入的对象,传入后函数的this就指向了这个对象,后面的参数为你为函数传递的参数值。

二、不同点

/*
* apply()方法
* 当后面参数个数确定用call,参数之间用逗号连接
*/
function.apply(thisObj[, argArray])
 
/*
* call()方法
* 当后面参数个数不确定时用apply,参数通过数组形式输入
*/
function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);

三、使用示例

  1. 基本使用
function add(a,b){return a+b};
function sub(a,b){return a-b};
console.log(add.apply(sub,[4,2])); // sub调用add的方法 6
console.log(sub.apply(add, [4,2]));// 2
// call
console.log(add.call(sub, 4, 2)); // 6
  1. 实现继承
function Animal (name) {
	this.name = name;
	this.showName = function () {
		console.log(this.name);
	}
}
function Cat (name) {
	Animal.apply(this, [name]);
	// call用法
	// Animal.call(this, name);
}
let cat  = new Cat('mimi')
  1. apply 的一些奇妙用法
    1. Math.max实现获取数组中的最大值:
      Math.max方法不支持数组,但是支持Math.max(p1,p2,p3,...), 所以利用apply的特点来解决:max=Math.apply(null, array)
      这样就轻易的可以得到一个数组中的最大项(apply会将一个数组转换为一个参数接一个参数的方式传递给方法)。这块在调用的时候第一个参数给了null,这是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,所以直接传递了一个null过去。用这种方法同样也可以实现得到数组中的最小项:Math.min.apply(null,array);
    2. Array.prototype.push()可以实现两个数组合并
      同样push方法没有提供push一个数组,但是它提供了push(param1,param2...paramN),同样也可以用apply来转换一下这个数组,即
var arr1=[1,2,3];
var arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2);  //得到合并后数组的长度,因为push就是返回一个数组的长度

通常在什么情况下,可以使用apply类似Math.max等之类的特殊用法:

一般在目标函数只需要n个参数列表,而不接收一个数组的形式,可以通过apply的方式巧妙地解决这个问题。

  1. call方法–验证是否是数组
function isArray(obj) {
	return Object.prototype.toString.call(obj) === '[object Array]';
}

四、手写实现

1.call实现

Function.prototype.myCall = function(context) {
  // 1.判断调用对象是否为函数
  if (typeof this !== "function") {
    throw new TypeError("Error");
  }
  // 2.判断 context 是否传入,如果未传入则设置为 window
  let context = context || window;
  // 3.获取参数
  let args = [...arguments].slice(1),
  let result = null;
  // 4.将调用函数设为对象的方法
  context.fn = this;
  // 5.调用函数
  result = context.fn(...args);
  // 6.将属性删除
  delete context.fn;
  //7.返回结果
  return result;
};

2.apply实现

Function.prototype.myapply = function(contex) {
    //1.判断是否为函数
    if(typeof this !== 'function') {
        throw new TypeError("Error");
    }
    //2.判断传入上下文是否存在
    let context = context ? constext : window;
    //3.将函数作为上下文的一个属性
    context.fn = this;
    //4.判断参数是否传入
    //5.使用上下文对象来调用这个方法
    let result= null;
    let args = arguments[1];
    if(args) {
        result = context.fn(...args);
    } else {
        result = context.fn();
    }
    //6.删除新增的属性
    delete contex.fn;
    //7.返回结果
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值