js中call与apply用法

转载 2012年03月28日 12:46:59

来源:http://blog.csdn.net/sunboy_2050/article/details/6592082

前天去面试,有个gg问了一些js知识,其中有一道call与apply用法的题目,尽管在365天前用过call方法,但当时还是没能答上来,今天深入总结一下

call和apply,它们的作用都是将函数绑定到另外一个对象上去运行

两者的格式和参数定义:

call( thisArg [,arg1,arg2,… ] );       // 参数列表,arg1,arg2,...

apply(thisArg [,argArray] );                 // 参数数组,argArray

上面两个函数内部的this指针,都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的

一、call 的简单用法

首先,我们先看个简单的例子(call):

  1. <!doctype html>  
  2.   
  3. <html>  
  4.     <head>  
  5.         <title> call-apply </title>  
  6.     </head>  
  7.   
  8.     <body>  
  9.         <input type="text" id="idTxt" value="input text">  
  10.           
  11.         <script type="text/javascript">  
  12.             var value = "global var";  
  13.               
  14.             function mFunc()  
  15.             {  
  16.                 this.value = "member var";  
  17.             }  
  18.               
  19.             function gFunc()  
  20.             {  
  21.                 alert(this.value);  
  22.             }         
  23.                                                       
  24.             window.gFunc();                                 // show gFunc, global var  
  25.             gFunc.call(window);                             // show gFunc, global var  
  26.             gFunc.call(new mFunc());                        // show mFunc, member var  
  27.             gFunc.call(document.getElementById('idTxt'));   // show element, input text  
  28.         </script>  
  29.           
  30.         <script language="javascript">  
  31.             var func = new function()  
  32.             {  
  33.                 this.a = "func";  
  34.             }  
  35.               
  36.             var func2 = function(x)  
  37.             {  
  38.                 var a = "func2";  
  39.                 alert(this.a);                
  40.                 alert(x);  
  41.             }  
  42.               
  43.             func2.call(func, "func2");                      // show func and func2  
  44.         </script>  
  45.     </body>  
  46. </html>  

然后,运行结果如下:

global var
global var
member var
input text
func
func2

测试环境:Google Chrome 10.0.648.45

最后,分析结果

1、全局对象window调用函数gFunc,this指向window对象,因此this.value为global var

2、函数gFunc调用call方法,this默认指向第一个参数window对象,因此this.value也为global var

3、函数gFunc调用call方法,this默认指向第一个参数new mFunc(),即mFunc的对象,因此this.value为mFunc的成员变量member var

4、函数gFunc调用call方法,this默认指向第一个参数input text控件,即id=‘idTxt’的控件,因此this.value为input控件的value值input text

5、函数func2调用call方法,this默认指向第一个参数func函数对象,因此this.value为this.a,即func

6、函数func2调用call方法,第二个参数属于函数对象func2的参数,因此alert(x)为第二个参数func2

二、call 继承用法与改进

js使用call模拟继承

测试代码:

  1. <!doctype html>  
  2.   
  3. <html>  
  4.     <head>  
  5.         <title> call - apply for inherit </title>  
  6.     </head>  
  7.       
  8.     <body>  
  9.         <script type="text/javascript">  
  10.             function baseA()        // base Class A  
  11.             {  
  12.                 this.member = "baseA member";  
  13.                 this.showSelfA = function()  
  14.                 {  
  15.                     window.alert(this.member);  
  16.                 }  
  17.             }  
  18.               
  19.             function baseB()        // base Class B  
  20.             {  
  21.                 this.member = "baseB member";  
  22.                 this.showSelfB = function()  
  23.                 {  
  24.                     window.alert(this.member);  
  25.                 }  
  26.             }  
  27.               
  28.             function extendAB()     // Inherit Class from A and B  
  29.             {  
  30.                 baseA.call(this);   // call for A  
  31.                 baseB.call(this);   // call for B  
  32.             }  
  33.               
  34.             window.onload = function()  
  35.             {  
  36.                 var extend = new extendAB();      
  37.                 extend.showSelfA();     // show A  
  38.                 extend.showSelfB();     // show B  
  39.             }  
  40.         </script>  
  41.     </body>  
  42. </html>  
运行结果如下:

baseB member

baseB member

测试环境:Google Chrome 10.0.648.45

结果分析:

预期的结果,应该是输出 baseA member 和 baseB member,但实际输出却是 baseB member 和 baseB member

(已在IE9、8、6,Maxthon、Chrome、FF、Opera、Safari、360等浏览器测试过,结果都是后者:baseB member)

至此,机器是不会错的,这就需要我们深入分析

我们可能会很容易想到是this引起的,this两次都指向了baseB对象,但是推测真是这样吗?

为了探究实质,我们借助chrome浏览器的调试工具,下断点,进行调试,结果发现:


当调用extend.showSelfA();时,此时的this指向extendAB(并不是我们推测的两次都指向baseB对象

真实原因是extendAB对象的成员变量member在被baseB.call(this);实例化时,被baseB的成员member覆盖了,即extendAB的成员member由baseA member赋值成了baseB member

当然,我们也可以对上面baseA代码稍作修改,来验证我们调试分析的正确性:

function baseA() // base Class A
{
this.memberA = "baseA member";   // member改成memberA,以区分baseB中的member
this.showSelfA = function()
{
window.alert(this.memberA);    // 显示memberA
}
}

再次运行chrome等浏览器,结果如下:

baseA  member

baseB member

结果和我们的预期相同,同时chrome调试信息也验证了我们的正确性:


继承改进(prototype)

以上模拟继承方法,仔细分析不是最好的。

因为每次在函数(类)中定义了成员方法,都会导致实例有副本,因此可以借助prototype原型,进行改进

改进举例如下:

  1. <!doctype html>  
  2.   
  3. <html>  
  4.     <head>  
  5.         <title> call - apply for prototype </title>  
  6.     </head>  
  7.       
  8.     <body>  
  9.         <script type="text/javascript">  
  10.             var Class = {  
  11.                 create: function()              // create Function  
  12.                 {  
  13.                     return function()  
  14.                     {  
  15.                         this.initialize.apply(this, arguments);  
  16.                     }  
  17.                 }  
  18.             };  
  19.               
  20.             var Person = Class.create();        // Create Class Person  
  21.             Person.prototype = {                // prototype initialize  
  22.                 initialize: function(obj1, obj2)  
  23.                 {  
  24.                     this.obj1 = obj1;  
  25.                     this.obj2 = obj2;  
  26.                 },  
  27.                 showSelf: function()  
  28.                 {  
  29.                     alert("obj: " + this.obj1 + " and " + this.obj2);  
  30.                 }  
  31.             }  
  32.               
  33.             // instance Class  
  34.             var person = new Person("man", "women");    // two params  
  35.             person.showSelf();                          // show person  
  36.         </script>  
  37.     </body>  
  38. </html>  
运行结果如下:
obj: man and women

js中call与apply的用法小结

js中call与apply的用法小结 本篇文章主要是对js中call与apply的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 前天去面试,有个gg问了一些j...
  • taoerchun
  • taoerchun
  • 2016年01月06日 21:25
  • 1621

js的call() ,apply() 两种方法的区别和用法,最白话文的解释,让枯燥滚粗!

背景:今天群里有 妹子(我就不指名道姓喽)说:百度了一圈calll()函数和apply()函数,感觉还是糊里糊涂然后群里热闹了,各种表情包,各种殷勤,你懂的!正好我前几天刚又重新翻了一遍 那本 600...
  • xllily_11
  • xllily_11
  • 2016年05月23日 13:17
  • 6781

JS中的call()方法和apply()方法用法总结

JacvaScript中的call()方法和apply()方法, 1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。 2. 相同点:这两个方法的作用是一样的。都是在特定的...
  • ganyingxie123456
  • ganyingxie123456
  • 2017年04月27日 15:14
  • 12527

Js中apply与call的区别与用法

解析:apply与call是更改对象的内部指针,即改变对象的this指向的内容。 call与apply的第一个参数都是要传入给当前对象的对象,及函数内部的this。后面的参数都是传递给当前对象的参数。...
  • wangji5850
  • wangji5850
  • 2016年03月17日 12:00
  • 1504

js中的call()和apply()方法

1.call() 语法:obj1.call(obj2[,param1,param2,...]) 定义:用obj2对象来代替obj1,调用obj1的方法。即将obj1应用到obj2上。 说明:ca...
  • mafan121
  • mafan121
  • 2016年10月25日 15:15
  • 1711

js中call,apply和bind方法的区别和使用场景

详解js中的call,apply和bind函数
  • yaojxing
  • yaojxing
  • 2017年05月14日 12:09
  • 1529

apply, call, bind在js中的区别

apply, call, bind在js中的区别在js中,这三种方法都是用来改变函数的this对象的指向的。先看看相似点: 都是用来改变函数的this对象的指向的 第一个参数都是this要指向的对...
  • xiaobing_hope
  • xiaobing_hope
  • 2016年07月20日 21:35
  • 1333

JavaScript 中的 this 用法以及 call(apply) 的理解

想要深入了解 JavaScript 这门语言,一个必须掌握的知识点就是对 `this` 的理解。其中, `call` 和 `apply` 又与 `this` 有着密切的联系。趁现在有空,在网上看了一些...
  • gertYY
  • gertYY
  • 2017年02月13日 13:53
  • 2275

JavaScript中apply与call的用法意义及区别

call()和apply的区别
  • laijieyao
  • laijieyao
  • 2015年02月03日 09:40
  • 5978

JS中call、apply、bind大概区别

为什么需要这些?主要是因为this,来看看this干的好事。box.onclick = function(){   function fn(){     alert(this);   }   fn()...
  • lizeshi125
  • lizeshi125
  • 2016年12月15日 14:53
  • 2537
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:js中call与apply用法
举报原因:
原因补充:

(最多只允许输入30个字)