优雅的理解 call 和 apply 的使用方法

news/2024/7/5 5:46:30
  • 作者在看到一篇优雅的使用 js 的各种方法解决算法的时候产生的疑问,到底什么时候使用 apply 和 call 啦?

  • 每次看到别人用 apply 和 call 其实从以前的懵懵懂懂到现在的明白,但是自己从来未下手去用过,最近比较闲。开始打一下 JavaScript 的算法基础,刷一下简单的算法题目。然后从自己拙劣的解题思路和方法比较大牛的优雅的JavaScript的方法后有所感想。

先来看一个?栗子

Q:将数组 arr 中的元素作为调用函数 fn 的参数

这里面涉及几个知识点,函数调用的方法,apply 和 call 的使用。

  • 创建函数
function argsAsArray(fn, arr) {// code here
}
复制代码
  • 输入
argsAsArray(function (greeting, name, punctuation) {return greeting + ', ' + name + (punctuation || '!');}, ['Hello', 'Ellie', '!']
)
复制代码
  • 输出

Hello, Ellie!
复制代码

看完上面的题目,大家知道怎么解题吗?(答案在本文最后)如果你想到了 apply 和 call,那么恭喜你,基础扎实,然后就是对 call 和 apply 的基本了解和掌握了。看下面?

怎么理解 apply 和 call

  • 第一步:看看 MDN 的解释
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
  • 第二步:跟着我看一个 demo
function cat(){};cat.prototype = {obj:"fish",say:function(){return "I love" + this.obj;}
}function doggie(){};doggie.prototype = {obj:"bone",eat:function(){return "I love" + this.obj;}
}function ATM(){};ATM.prototype = {obj:"monster",fight:function(){return "I love" + this.obj;}
}复制代码
  • 上面的理解?:猫吃鱼,狗吃肉(骨头),奥特曼爱打小怪兽。

突然有一天:

  • 有天狗想吃鱼了

cat.say.call(doggie,cat.obj)
//猫.吃鱼.call(狗,鱼)//狗就吃到鱼了复制代码
  • 猫成精了,想打怪兽
ATM.fight.call(cat,ATM.obj)//奥特曼.打小怪兽.call(猫,小怪兽)复制代码

就这样记住了。

来训练一下实战怎么优雅(强行)的用上 apply 和 call

  • Q:删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组
  • 输入 : [1,2,3,4]
  • 输出 : [1,2,3]

很简单对不对,不删除原来的数组,我们 clone 一个数组。然后使用 JavaScript 自带的数组方法 pop() 就行了。

  • 解法一

function truncate(arr) {var newArr = arr.slice(0);// slice(0) 复制数组newArr.pop();return newArr;
}复制代码

当然你可以优雅的使用 slice 来搞定

  • 解法二

function truncate(arr) {return arr.slice(0,-1);
}复制代码

现在问题来了,我们要用 apply 来搞定问题咋办啦?(实现一个数组 copy)

还是创建一个新的数组,我们明白了凹凸曼和小猫小狗的用法以后,我们将 newArr 借用 [] 数组的 push 方法,对象是 arr,而达到 copy 一个数组的功能。


function truncate(arr) {var newArr=[];[].push.apply(newArr, arr);newArr.pop();return newArr;
}
复制代码

当然有很多可供实现的 apply 的使用情况,可能我这个不是很确切,大家可以鞭策一下,共同学习和理解

A(最开始题目的答案)

function argsAsArray(fn, arr) {return fn.apply(this,arr);
}
复制代码

这里解释两个点

  • 一,调用函数有几种方法?
    • 直接调用: obj.func()
    • call: func.call(obj,arg) // 列出参数
    • apply: func.apply(obj,[a,b,c,...]) // 列出数组
  • 二,call 和 apply 的区别
    • 般情况下都是对象调用函数,但此处是函数调用数组对象,用call(), apply()。第一个参数是传给当前函数对象。但是call()需要将参数挨个列出,apply直接传入数组对象。

http://lihuaxi.xjx100.cn/news/238350.html

相关文章

为什么基于区块链的系统比您认为的更高效

想知道更多区块链技术知识,请百度【链客区块链技术问答社区】 链客,有问必答!我们最近见证了Web是如何深刻地改变了各种业务的,其中包括市场的实现方式:Web驱动的市场通常遵循这种模式。 在这个方案中,我主要关注实现…

Sqoop的基础应用

实验目的要求 了解ET了工具Sqoop;学会安装配置Sqoop;学会使用数据迁移框架Sqoop;使用Sqoop导入MySQL到HDFS和Hive;使用Sqoop导出HDFS数据到MySQL; 实验环境 Java jdk 1.7;apache-maven-3.6.0;…

编码和编码格式一样吗?_学习如何像专业人士一样编码

编码和编码格式一样吗?Learn how to write more professional code from Dylan Israel. Dylan teaches about tools and principles to improve your code that hes found helpful in his job as a developer.从Dylan Israel了解如何编写更专业的代码。 Dylan教授有关改善您的…

区块链的分布式网络结构有哪些特点?

想知道更多区块链技术知识,请百度【链客区块链技术问答社区】 链客,有问必答!!区块链建立的物理网络基础是点对点的分布式网络,这与中心化的“客户端/服务器”网络架构有很大不同,它是一种去中心化的网络&a…

SpringBoot+Docker+Git+Jenkins实现简易的持续集成和持续部署

前言 本篇文章引导你使用Jenkins部署[SpringBoot项目],同时使用Docker和Git实现简单的持续集成和持续部署。(项目地址:sso-merryyou) 流程图如下: push代码到Github触发WebHook。(因网络原因,本篇使用gitee…

Spark的基础应用

目的要求 搭建Spark集群环境;Spark集群的启动、浏览与关闭;使用Eclipse编写Spark应用程序包;如何运行Spark任务; 实验环境 Java jdk 1.7;apache-maven-3.6.0;Eclipse;Apache_Hadoop集群&#…

以太坊中的安全代币案例

想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】 链客 ,有问必答!我在关于安全令代币(第一部分,第二部分)有争议的文章中,我提到过,以太坊可能不是长期执行安全代币…

mysql查看正在执行的sql语句

有2个方法: 1、使用processlist,但是有个弊端,就是只能查看正在执行的sql语句,对应历史记录,查看不到。好处是不用设置,不会保存。 -- use information_schema; -- show processlist; 或者: -- …