javascript函数apply和call
apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
call:和apply的意思一样,只不过是参数列表不一样.
Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表
1. apply示例:
- <script type="text/javascript">
- /*定义一个人类*/
- function Person(name,age)
- {
- this.name=name;
- this.age=age;
- }
- /*定义一个学生类*/
- functionStudent(name,age,grade)
- {
- Person.apply(this,arguments);
- this.grade=grade;
- }
- //创建一个学生类
- var student=new Student("zhangsan",21,"一年级");
- //测试
- alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
- //大家可以看到测试结果name:zhangsan age:21 grade:一年级
- //学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
- </script>
分析: Person.apply(this,arguments);
this:在创建对象在这个时候代表的是student
arguments:是一个数组,也就是[“zhangsan”,”21”,”一年级”];
也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面
2. call示例
在Studen函数里面可以将apply中修改成如下:
Person.call(this,name,age);
这样就ok了
3. 什么情况下用apply,什么情况下用call
在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply , 如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));
4. apply的一些其他巧妙用法
细心的人可能已经察觉到,在我调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合, 在调用Person的时候,他需要的不是一个数组,但是为什么他给我一个数组我仍然可以将数组解析为一个一个的参数,这个就是apply的一个巧妙的用处,可以将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 param1,param2,param3) 这个如果让我们用程序来实现将数组的每一个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法:
a) Math.max 可以实现得到数组中最大的一项
因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组
但是它支持Math.max(param1,param2,param3…),所以可以根据刚才apply的那个特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项(apply会将一个数组装换为一个参数接一个参数的传递给方法)
这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,.所以直接传递了一个null过去
b) Math.min 可以实现得到数组中最小的一项
同样和 max是一个思想 var min=Math.min.apply(null,array);
c) Array.prototype.push 可以实现两个数组合并
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:
- vararr1=new Array("1","2","3");
- vararr2=new Array("4","5","6");
- Array.prototype.push.apply(arr1,arr2);
也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.
通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:
一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题!
1、每个函数都包含两个非继承而来的方法:apply()和call()。
2、他们的用途相同,都是在特定的作用域中调用函数。
3、接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。
例1:
window.lastName = "song";
var myObject = { firstName: "my", lastName: "Object" };
function HelloName() {
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");
}
HelloName.call(window); //huo .call(this);
HelloName.call(myObject);
运行结果为:
Hello diz song glad to meet you!
Hello my Object glad to meet you!
例2:
return num1 + num2;
}
console.log(sum.call(window, 10, 10)); //20
console.log(sum.apply(window,[10,20])); //30
分析:在例1中,我们发现apply()和call()的真正用武之地是能够扩充函数赖以运行的作用域,如果我们想用传统的方法实现,请见下面的代码:
window.lastName = "song";
var myObject = { firstName: "my", lastName: "Object" };
function HelloName() {
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");
}
HelloName(); //Hello diz song glad to meet you!
myObject.HelloName = HelloName;
myObject.HelloName(); //Hello my Object glad to meet you!
见加红的代码,我们发现,要想让HelloName()函数的作用域在对象myObject上,我们需要动态创建myObject的HelloName属性,此属性作为指针指向HelloName()函数,这样,当我们调用myObject.HelloName()时,函数内部的this变量就指向myObjecct,也就可以调用该对象的内部其他公共属性了。
通过分析例2,我们可以看到call()和apply()函数的真正运用之处,在实际项目中,还需要根据实际灵活加以处理!
一个小问题:再看一看函数中定义函数时,this变量的情况
console.log(this); //Object {}
function temp2() {
console.log(this); //Window
}
temp2();
}
var Obj = {};
temp1.call(Obj); //运行结果见上面绿色的注释!!!!
执行结果与下面的相同:
console.log(this);
temp2();
}
function temp2() {
console.log(this);
}
var Obj = {};
temp1.call(Obj);
4、bind()方法
支持此方法的浏览器有IE9+、Firefox4+、Safari5.1+、Opera12+、Chrome。它是属于ECMAScript5的方法。直接看例子:
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
var OSayColor = sayColor.bind(o);
OSayColor(); //blue
5. 总结:
一开始我对apply 非常的不懂,最后多看了几遍,自己多敲了几遍代码,才明白了中间的道理,所以,不管做什么事情,只要自己肯动脑子,肯动手敲代码,这样一个技术就会掌握…
还有比如第四部分得内容,巧妙的解决了实实在在存在的问题,这个肯定不是一个初学者能想到的解决方案(这个也不是我自己想的),没有对编程有一定认识的不会想到这个的,还是一句话,多积累,多学习,提升自己的能力和对编程思想的理解能力才是最关键!
javascript函数apply和call的更多相关文章
- 瞬间记住Javascript中apply与call的区别
关于Javascript函数的apply与call方法的用法,网上的文章很多,我就不多话了.apply和call的作用很相似,但使用方式有区别 apply与call的第一个参数都是一个对象,这个对象就 ...
- JavaScript权威设计--JavaScript函数(简要学习笔记十一)
1.函数调用的四种方式 第三种:构造函数调用 如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内.这和函数调用和方法调用是一致的.但如果构造函数没有形参,JavaScri ...
- Javascript函数重载,存在呢—还是存在呢?
1.What's is 函数重载? );//Here is int 10 print("ten");//Here is string ten } 可以发现在C++中会根据参数的类型 ...
- javascript 函数重载 overloading
函数重载 https://en.wikipedia.org/wiki/Function_overloading In some programming languages, function over ...
- JavaScript语言精粹读书笔记 - JavaScript函数
JavaScript是披着C族语言外衣的LISP,除了词法上与C族语言相似以外,其他几乎没有相似之处. JavaScript 函数: 函数包含一组语句,他们是JavaScript的基础模块单元,用于代 ...
- (转)深入浅出 妙用Javascript中apply、call、bind
原文连接 深入浅出 妙用Javascript中apply.call.bind 网上文章虽多,大多复制粘贴,且晦涩难懂,我希望能够通过这篇文章,能够清晰的提升对apply.call.bind的认识,并且 ...
- 深入理解javascript函数系列第一篇——函数概述
× 目录 [1]定义 [2]返回值 [3]调用 前面的话 函数对任何一门语言来说都是一个核心的概念.通过函数可以封装任意多条语句,而且可以在任何地方.任何时候调用执行.在javascript里,函数即 ...
- 深入理解javascript函数系列第三篇——属性和方法
× 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...
- JavaScript函数之美~
JavaScript函数之美~ 这篇文章,我将就以下几个方面来认识JavaScript中的函数. 函数为什么是对象,如何定义函数? 如何理解函数可以作为值被传递 函数的内部对象.方法以及属性 第一部分 ...
随机推荐
- C#编程建言笔记
方法: 1.方法(静态或实例)JIT编译后,在内存中的代码段上都是一个全局函数,且只存在一份拷贝. 2.方法修饰符:保护级别,静态,虚函数:方法签名:返回值,函数名,参数. 构造器: 1.一个方法只能 ...
- VB.NET数据库编程基础教程
关键词:作者罗姗 众所周知,VB.NET自身并不具备对数据库进行操作的功能,它对数据库的处理是通过.NET FrameWork SDK中面向数据库编程的类库和微软的MDAC来实现的.其中,ADO. ...
- Fedora、CentOS install TTF/otf fonts
Step 1:切换至字体下载目录: [Richard@localhost Downloads]$ ll | grep otf -rw-rw-r--. Richard Richard 7月 RBNo2L ...
- 最近做OpenWrt的总结
用到了哪些东西 需要在OpenWrt上开发一个客户端,用C语言写还比较方便,最开始在linux上跑,后面移植到路由器上,做成ipk.除了稍微修改了下Makefile,其他的什么都没改. 因为需要做个配 ...
- mysql 按日期查询
在mysql中,比如你的表的时间字段是column2,并且column2的类型是timestamp 单日查询: select * from TableName where column1='xxxx' ...
- 小鱼提问3 static方法中可以访问某个类的私有变量吗(不通过反射的其他非正常手段)?什么情况下可以?
class Student { private string _name; public int Age = 0; public static void Test() { Student stu = ...
- CentOS yum安装配置lnmp服务器(Nginx+PHP+MySQL)
1.配置防火墙,开启80端口.3306端口 vi /etc/sysconfig/iptables-A INPUT -m state --state NEW -m tcp -p tcp --dport ...
- jquery结合highcharts插件显示实时数据动态曲线图
效果如图所示: js代码如下: $(document).ready(function() { Highcharts.setOptions({ global: { useUTC: false }, co ...
- Prepare Python environment and install selenium.
1, Install python and selenium. I use python 3.5, the following is the example 1.) Python downloa ...
- Httpwatch 工具介绍
一 概述: HttpWatch强大的网页数据分析工具.集成在Internet Explorer工具栏.包括网页摘要.Cookies管理.缓存管理.消息头发送/接受.字符查询.POST 数据和目录管理功 ...