js中call与apply用法

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

两者的格式和参数定义:

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

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

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

一、call 的简单用法

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

<!doctype html>
<html>
   <head>
 <title> call-apply </title>
   </head>
 <body>
  <input type="text" id="idTxt" value="input text">
  <script type="text/javascript">
   var value = "global var";
   function mFunc()
   {
    this.value = "member var";
   }
   function gFunc()
   {
    alert(this.value);
   }   
   alert("开始1");       
   window.gFunc(); // global var
   alert("begin call windows object");
   gFunc.call(window); // global var
   alert("begin call mFunc object");
   gFunc.call(new mFunc()); // member var
   alert("begin call idTxt object");
   gFunc.call(document.getElementById('idTxt'));  // show element, input text
  </script>
  <script language="javascript">
   var func = new function()
   {
    this.a = "func";
   }
   var func2 = function(x)
   {
    var a = "func2";
    alert(this.a);   
    alert(x);
   }
   alert("开始2");
   func2.call(func, "func2");      // func  func2
  </script>
 </body>
</html>

 

然后,运行结果如下:
global var
global var
member var
input text
func
func2

最后,分析结果
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模拟继承
测试代码:
<!doctype html>
<html>
 <head>
  <title> call - apply for inherit </title>
 </head>
 <body>
  <script type="text/javascript">
   function baseA()  // base Class A
   {
    this.member = "baseA member";
    this.showSelfA = function()
    {
     window.alert(this.member);
    }
   }
   function baseB()  // base Class B
   {
    this.member = "baseB member";
    this.showSelfB = function()
    {
     window.alert(this.member);
    }
   }
   function extendAB()// Inherit Class from A and B
   {
    baseA.call(this); // call for A
    baseB.call(this); // call for B
   }
   window.onload = function()
   {
    var extend = new extendAB(); 
    extend.showSelfA();  // show A
    extend.showSelfB();  // show B
   }
  </script>
 </body>
</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原型,进行改进
改进举例如下:
<!doctype html>
<html>
 <head>
  <title> call - apply for prototype </title>
 </head>
 <body>
  <script type="text/javascript">
   var Class = {
    create: function()    // create Function
    {
     return function()
     {
      this.initialize.apply(this, arguments);
     }
    }
   };
   var Person = Class.create();// Create Class Person
   Person.prototype = { // prototype initialize
    initialize: function(obj1, obj2)
    {
     this.obj1 = obj1;
     this.obj2 = obj2;
    },
    showSelf: function()
    {
     alert("obj: " + this.obj1 + " and " + this.obj2);
    }
   }  
   // instance Class
   var person = new Person("man", "women"); // two params
   person.showSelf();  // show person
  </script>
 </body>
</html>
运行结果如下:
obj: man and women

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值