不用不知道 apply()与call()的强大
在看关于javascript继承的时候 好多地方都用到了apply()和call() 之前在简单编程的时候根本没有遇到过 查阅资料后才发现这两个方法是如此的好用。
下面从几方面来看一下这两个方法:
1、定义
2、从例子中详解
3、在实际应用中让人意想不到的拓展
一、首先从定义入手:
apply()和call()都是定义在Function对象原型上的方法(Function.prototype.apply = function(){}&Function.prototype.call = function(){}),故可以直接使用。
apply():调用函数,并用指定对象替换函数的 this 值,同时用指定数组替换函数的参数。
apply([thisObj[,argArray]])
- argArray可选。 要传递到函数的一组参数。
- 备注
<script type="text/javascript">
function Animal(name,color){
this.name = name;
this.color = color;
this.type = "animal";
} function Bird(name,color,age){
Animal.apply(this,arguments);//此时Animal中this 指向的是windows故需要使用apply()方法将this的指向改为 Bird实例
this.age = age;
} var sparrow = new Bird("bage","yellow","1");
console.log("Hello,my name is "+sparrow.name+",my color is "+sparrow.color+".I am "+sparrow.age+" years old.I am a "+sparrow.type);
</script>
//输出结果:Hello,my name is bage,my color is yellow.I am 1 years old.I am a animal √
这个简单的例子实现了一个Bird继承Animal构造函数的方法,如果换为一下代码:
<script type="text/javascript">
function Animal(name,color){
this.name = name;
this.color = color;
this.type = "animal";
} function Bird(name,color,age){
Animal(name,color);
this.age = age;
} var sparrow = new Bird("bage","yellow","1");
console.log("Hello,my name is "+sparrow.name+",my color is "+sparrow.color+".I am "+sparrow.age+" years old.I am a "+sparrow.type); </script>
//输出结果:Hello,my name is undefined,my color is undefined.I am 1 years old.I am a undefined ×
在apply()中的参数arguemts 是Javascript Function对象的属性(Function对象的7个属性和5个方法 https://msdn.microsoft.com/zh-cn/library/x844tc74(v=vs.94).aspx),获取当前正在执行的 Function 对象的参数, arguments 对象中包含的各个参数的访问方式与数组元素的访问方式相同。
即,在本例中指的是["bage","yellow","1"],这也是apply与call最主要的区别。
而,apply()中的参数this 指向是Bird的实例sparrow
2、call()
<script type="text/javascript>
function Animal(name,color){
this.name = name;
this.color = color;
this.type = "animal";
} function Bird(name,color,age){
Animal.call(this,name,color);
this.age = age;
} var sparrow = new Bird("bage","yellow","1");
console.log("Hello,my name is "+sparrow.name+",my color is "+sparrow.color+".I am "+sparrow.age+" years old.I am a "+sparrow.type); </script>
//输出结果:Hello,my name is bage,my color is yellow.I am 1 years old.I am a animal √
3、什么时候用apply() 什么时候用call()
<script type="text/javascript>
function Animal(color,name){
this.name = name;
this.color = color;
this.type = "animal";
} function Bird(name,color,age){
Animal.apply(this,arguments);
this.age = age;
} var sparrow = new Bird("bage","yellow","1");
console.log("Hello,my name is "+sparrow.name+",my color is "+sparrow.color+".I am "+sparrow.age+" years old.I am a "+sparrow.type); </script>
//输出结果:Hello,my name is yellow,my color is bage.I am 1 years old.I am a animal ×
<script type="text/javascript">
function Animal(color,name){
this.name = name;
this.color = color;
this.type = "animal";
} function Bird(name,color,age){
Animal.call(this,color,name);
this.age = age;
} var sparrow = new Bird("bage","yellow","1");
console.log("Hello,my name is "+sparrow.name+",my color is "+sparrow.color+".I am "+sparrow.age+" years old.I am a "+sparrow.type); </script>
//输出结果Hello,my name is bage,my color is yellow.I am 1 years old.I am a animal √
从两个例子中不难看出,apply()的arguments 不会考虑“子类”和“父类”之间的参数顺序问题,默认参数顺序一致,当不一致时会出现赋值的混乱,而使用call()手动赋值可以保证与“父类”的参数一致。
细心的人可能已经察觉到,在我调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合, 在调用Person的时候,他需要的不是一个数组,但是为什么他给我一个数组我仍然可以将数组解析为一个一个的参数,这个就是apply的一个巧妙的用处,可以将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 param1,param2,param3) 这个如果让我们用程序来实现将数组的每一个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法:
1、Math.max 可以实现得到数组中最大的一项
因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组
但是它支持Math.max(param1,param2,param3…),所以可以根据刚才apply的那个特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项(apply会将一个数组装换为一个参数接一个参数的传递给方法)
这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,.所以直接传递了一个null过去
2、Math.min 可以实现得到数组中最小的一项
同样和 max是一个思想 var min=Math.min.apply(null,array);
3、Array.prototype.push 可以实现两个数组合并
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:
1 vararr1=new Array("1","2","3");
2
3 vararr2=new Array("4","5","6");
4
5 Array.prototype.push.apply(arr1,arr2);
也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.
通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:
一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题!
不用不知道 apply()与call()的强大的更多相关文章
- 函数的属性和方法之call、apply 及bind
一.前言 ECMAScript中的函数是对象,因此函数也有属性和方法.每个函数都包含两个属性:length和prototype.每个函数也包含两个非继承来的方法:apply()和call(),还有一些 ...
- 函数对象的apply()和call()方法
每个函数都包含两个非继承而来的方法:apply()和call().这两个方法的用途都是在特定的作用域中调用函数,特定的作用域为this参数指定的对象. apply()和call()真正强大的地方是能够 ...
- 泛函编程(25)-泛函数据类型-Monad-Applicative
上两期我们讨论了Monad.我们说Monad是个最有概括性(抽象性)的泛函数据类型,它可以覆盖绝大多数数据类型.任何数据类型只要能实现flatMap+unit这组Monad最基本组件函数就可以变成Mo ...
- javascript高级程序设计一(80-116)
81.函数内部属性:arguments.arguments.callee.this. window.color = "red"; var o={color:"blue&q ...
- R语言︱机器学习模型评估方案(以随机森林算法为例)
笔者寄语:本文中大多内容来自<数据挖掘之道>,本文为读书笔记.在刚刚接触机器学习的时候,觉得在监督学习之后,做一个混淆矩阵就已经足够,但是完整的机器学习解决方案并不会如此草率.需要完整的评 ...
- 快速学习 javascript
// js 6种数据类型:字符串.数值.布尔值.undefined.null.object // 三种非数字的数字类型:Infinity -Infinity NaN var str = "H ...
- JavaScript读书笔记(6)-Function
Function类型 ECMAScript中函数是对象,每个函数都是Function类型的实例,也有属性和方法,函数是对象,函数名实际上市一个指向函数对象的指针,不会与某个函数绑定: function ...
- 关于javascript中this 指向的4种调用模式
this指向问题绝对可以排js 的top 5最难和最重点的问题,初学者常常搞不清楚this指向哪里,特别是学过java和c#的人,想当年俺也迷糊了好久,直到遇到蝴蝶书,主要是因为js和主流的面向对象语 ...
- javascript中apply和eval结合的强大用法
eval是一个函数,可以接受一个参数,这个参数可以作为js语句被解释性的执行,利用这个特性,eval和apply结合起来,可以大大简化代码 如下例子 <a class="cl ...
随机推荐
- Android再学习-20140928-布局
关于布局中的单位 PX是像素,这个没有问题.另外还有两个单位,一个是dp,这个是个相对单位,在任何分辨率的屏幕上显示效果是一样的,所以用dp来进行控件的大小设置.另外,字体的设置推荐用sp,这样字体可 ...
- 帝国cms7.0整合百度编辑器ueditor教程
帝国cms7.0整合百度编辑器ueditor教程开始 1.根据自己使用的帝国cms版本编码下载对应的ueditor版本 下载地址 http://ueditor.baidu.com/website/do ...
- jQuery对象与DOM对象的互相转换
jQuery对象转换成DOM对象jQuery提供了两种方法将一个jQuery对象转换成DOM对象,即[index]和get(index).1.jQuery对象是一个数组对象,可以通过[index]的方 ...
- DDP和DDU什么区别
DU/DDP 就是A发货给国外B,B只要呆在家里看电视,货会自动送上门,当中的所有运输清关等事情都是由A来负责(A可以委托货代来负责),区别就是DDU是不包括税金的,也就是货值的百分之多少,税金会在B ...
- Qt编程之d指针与q指针
我们在Qt中可以看到两个宏Q_D和Q_Q这两个红分别是取得d指针和q指针的,d指针指向封装的私有类,q指针指向公共的类.(我的理解类似于回调,回指的意思). 为什么Qt要这样实现呢?下面几个链接中的文 ...
- bzoj1753 [Usaco2005 qua]Who's in the Middle
Description FJ is surveying his herd to find the most average cow. He wants to know how much milk th ...
- C# 文件夹操作
追加文件 StreamWriter sw = File.AppendText(Server.MapPath(] != Path.DirectorySeparatorChar) a ...
- java中File类的相关学习
File类 1.关于系统路径分割符. 在Windows中,使用反斜杠“\”作为路径分割符,比如“c:\test”,但是java中反斜杠表示转义,所以需要用“C:\\test”在程序中来表示路径.还可以 ...
- vmware虚拟机迁移系统到其它磁盘(xjl456852原创)
有时我们将vmware安装的系统放在了磁盘空间比较小的盘里,后来磁盘空间不够用了,我们需要将文件移动到其它磁盘.腾出这个磁盘的空间. 我安装的系统有10个,总占空间大小170多GB.需要从D盘迁移到G ...
- 数据库中简单的增删改查(CRUD)
一切都是基于数据,而对数据的管理都离不开数据库.最近学到数据库的简单操作,所以写下这篇文章,总结一下学习到的知识.浅陋之处,多多见谅. 补充一下:一直弄不清SQL Server,Mysql ,以及Or ...