博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速理解JavaScript中call和apply原理
阅读量:6823 次
发布时间:2019-06-26

本文共 2119 字,大约阅读时间需要 7 分钟。

在了解call()apply()原理之前,我们必须对this的作用和使用方法有所了解,如果你熟悉this 的用法,那么请直接往下看。

call方法:

语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])

定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法:

语法:apply([thisObj[,argArray]])

定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

call()apply()的作用十分相似,只是参数类型上的差别,以适应不同的使用场景。它们都是为了改变函数运行时的 context(上下文)而存在的,再说的直白一点,就是为了改变函数内部 this 的指向。

举例说明

我们有一句很经典的谚语,说的是:龙生龙,凤生凤,老鼠生来会打洞,这从遗传上解释是,动物的某些行为有可能是由一系列基因所调控的,但是,注意,我们偏偏想让龙来打洞呢,该如何去实现?下面将围绕这个话题来解释call()apply()的原理。

var dragon = {	name : 'foo'	// other attribute}var mouse = {	name : 'tom',	makeHole : function(where){		console.log(this.name + ' is making a hole in the ' + where)	}	// other attribute}mouse.makeHole.call(dragon,'hill')复制代码

运行上面代码后会在控制台上打印出:

可以看出,我们声明了一个dragon的对象,我们并没有赋予它打洞的功能,但是我们使用call()继承了mouse的方法,就可以做到mouse函数所能做到的事情。

这到底是怎么做到的呢?让我们来看看call()的参数: 第一个是一个对象,这个对象将代替Function类里原本的this对象,我们传入的是this,记住,这个thismakeHole函数里指的是未来将要实例化这个函数的对象(我知道这有些拗口),当声明了dragon的时候,这个this指的就是dragon。除了第一个参数,后面所有的参数都是传给父函数本身使用的参数。

apply()call()功能几乎一样,唯一的区别就是apply()第二个参数只能是数组,这个数组将作为参数传给原函数的参数列表arguments

模拟实现call()函数

call()函数是什么样的原理呢?我们用一个实例来帮助理解。

//创建Dragonfunction Dragon(name) {  this.name = name;}//创建一个说话的函数function say(content) {  console.log(this.name + ' : ' + content)}//模拟原生call函数Function.prototype.myCall = function(context) {  context = context || window;    var args = [];  context.fn = this;  for (var i = 1; i < arguments.length; i++) {    args.push(arguments[i]);  };    context.fn(...args);  delete context.fn;};//实例化一个名字为'foo'的龙var foo = new Dragon('foo')//让foo说话say.myCall(foo, 'I can talk!')复制代码

上面的代码很容易理解,唯一的困难点在于理解在原型链上的myCall函数 我们来分析实现的步骤:

  1. 做一个多场景适配,当myCall函数没有接收到参数时,context对应的是window对象
  2. 创建一个空数组,用于接收形参。
  3. 绑定this,这里的this代表的就是上下文中的say函数。
  4. for循环将参数添加到args数组,循环从1开始是因为第0位是foo对象,并非我们需要的参数
  5. 执行函数,并将args数组作为rest参数传入,这里是ES6的写法,不熟悉的同学参见阮一峰老师的文档
  6. 删除函数

打印结果为:

可以看到,这里我们实现了让一个叫做foo的龙说话! apply()函数实现方式同样类似,可以修改上述例子实现,主要是在参数一部分做处理。

转载地址:http://vmrzl.baihongyu.com/

你可能感兴趣的文章
Spring事务的传播属性和事务隔离级别
查看>>
关于maven
查看>>
Python入门到进阶,这本书有什么不同?
查看>>
资深专家深度剖析Kubernetes API Server第3章(共3章)
查看>>
【NLP】揭秘马尔可夫模型神秘面纱系列文章(一)
查看>>
在简书中使用Latex书写数学公式
查看>>
oracle系统包—-dbms_output用法
查看>>
py编程技巧-0.0-目录索引篇
查看>>
阿里云副总裁孙磊:Game Master,赋予游戏新智慧
查看>>
使用gulp构建你的前端项目
查看>>
SSM-SpringMVC-01:SpringMVC是什么?SpringMVC执行流程
查看>>
Android CardView设置成普通的Framelayout
查看>>
全球数字化报告 2019 发布:每 11 秒产生一位网络新人
查看>>
Vue - 实战疑点总结
查看>>
C#异步编程
查看>>
Sklearn-GridSearchCV网格搜索
查看>>
Facebook构建高性能Android视频组件实践之路
查看>>
企业级分布式监控系统--zabbix
查看>>
霍金去世 享年76岁
查看>>
Python3——随机漫步生成数据并绘制
查看>>