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

一、相同点

作用:都是用于改变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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值