今天深入总结一下
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);
- }
- window.gFunc(); // show gFunc, global var
- gFunc.call(window); // show gFunc, global var
- gFunc.call(new mFunc()); // show mFunc, member var
- 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);
- }
- func2.call(func, "func2"); // show func and func2
- </script>
- </body>
- </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模拟继承
测试代码:
- <!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
相关推荐
在JavaScript中,`call` 和 `apply` 是两种非常重要的函数调用方式,它们都用于改变函数执行时的上下文,即`this`的指向。本文将深入探讨这两种方法的用法及其在实际编程中的应用。 ### 1. `call` 的基本用法 `...
在JavaScript中,`call`和`apply`是两个非常重要的方法,它们都用于改变函数调用时的上下文(即`this`的值),并且可以灵活地传递参数。本篇文章将深入探讨这两个方法的用法、区别以及实际应用场景。 `call`方法...
接下来,`apply`的用法与`call`类似,但参数传递方式不同。`apply`的语法是`func.apply(context, [argsArray])`。这里,`context`同样用于指定`this`的值,而`argsArray`是一个数组或类数组对象,其元素会被作为单独...
### JavaScript中的apply与call用法详解 #### 一、引言 在JavaScript中,`apply`与`call`是两个非常重要的函数,它们都属于`Function.prototype`的一部分,因此每一个函数对象都拥有这两个方法。这两个方法的主要...
JavaScript中的`call`和`apply`是两种非常关键的方法,它们允许我们改变函数内部`this`的指向,同时也为实现模拟继承提供了可能。虽然JavaScript不直接支持类继承,但通过`call`和`apply`,我们可以实现类似的效果。...
在JavaScript中,call与apply是两个非常重要的关键字,它们的功能是改变函数执行时的上下文,也就是函数体内的this指向。通过call和apply可以调用某个函数,并且显式地指定该函数内部的this变量的值。 ### call和...
在JavaScript中,`call`和`apply`是两种非常重要的函数调用方式,它们都用于改变函数执行时的上下文,即改变`this`的指向。这两个方法的主要区别在于它们处理参数的方式。 `call`方法允许你指定一个对象来替代原...
在JavaScript中,实现对象继承主要有三种方式:原型链继承(prototype)、构造函数继承和call/apply继承。下面将分别详细介绍这三种继承方式的具体用法和实现原理。 1. 原型链继承(prototype) 原型链继承是...
### 理解JavaScript中的`caller`, `callee`, `call`, `apply` #### Arguments对象:JavaScript函数调用的参数管理器 在JavaScript中,每个函数都有一个隐含参数`arguments`,它允许开发者访问传递给函数的所有参数...
本文实例讲述了javascript中call,apply,bind函数用法。分享给大家供大家参考,具体如下: 一.call函数 a.call(b); 简单的理解:把a对象的方法应用到b对象上(a里如果有this,会指向b) call()的用法:用在函数上面 ...
在JavaScript中,`call`...总的来说,`call` 和 `apply` 在JavaScript的继承和上下文控制中起着关键作用,理解它们的用法有助于编写更加灵活和高效的代码。根据具体情况选择适合的方法,可以更好地适应不同场景的需求。
### JavaScript中apply、call和bind的用法区分 在JavaScript编程中,`apply`、`call`和`bind`这三个方法被广泛用于改变函数内部`this`的指向,这对于理解和编写复杂的JavaScript代码至关重要。虽然它们的功能相似,...
总的来说,JavaScript中的`call`和`apply`方法是非常有用的工具。它们可以用来控制函数调用的上下文,这在函数式编程和面向对象编程中都非常重要。同时,它们也为我们实现代码的复用和扩展提供了一种方式,尤其是在...
总结来说,apply、call和bind是JavaScript中非常重要的函数方法,它们提供了控制函数上下文的能力,无论是直接调用函数、扩展数组元素,还是改变对象的方法调用,这些方法都是不可或缺的工具。掌握它们的用法,能够...
call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是...
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向 语法: apply() 接收两...
### JavaScript中call与apply方法的学习笔记 在JavaScript编程中,`call`和`apply`是两个非常重要的方法,它们都是`Function`原型上的方法,用于改变函数的`this`上下文(即函数体内`this`的指向)到指定的对象,并...