1)无疑关于call,最简单的解释就是:把隐藏的第一个参数显示化。因为通常一个函数(Function)的调用,会有一个额外的隐藏参数,就是函数(Function)所属的对象(如果没有所特指,则为global(如window)对象),在函数内你可用this关键字访问之。
从call的构造式 -- call(thisArg[,arg1,arg2…] ]);可看出
call(apply)方法可将一个函数的对象上下文(Function Context)从初始的上下文改变为由 thisObj 指定的新对象,这就是利用call(apply)的最大优势。说到此,我们不妨提提所谓的Function Context到底是为何物。先看看下面FunctionContextDemo:
var changed={ item:"banana", act: "eating" };
var original={
item: "chair",
act: "sitting in",
ask: function(){
return "who's been "+this.act+" my "+this.item;
}
};
alert("Original : " + original.ask());
alert("Not so simple,that have been changed to: " + original.ask.call(changed));
解析上述代码:
最初存在2个对象changed和original,changed即就是一个数组,分别有item和act属性,而original除了具有和changed一样的item和act属性,还具有一个ask函数(询问到底是谁坐在椅子上),故当调用original.ask()时,可以看到意料中的结果:who's been sitting in my chair.而仔细往下看,当我们调用original.ask.call(changed)时,你觉得会出现什么的结果呢?在此,是利用了call把original的方法(函数)ask给与changed对象来执行,原来changed是没有ask方法(函数),如此绑定之后,函数的对象上下文(Function Context)即就是changed对象,故在方法(函数)ask里所调用的this就应该是changed对象,则可推知original.ask.call(changed)的结果应该是:who's been eating my banana.
通过FunctionContextdemo例子可看出如果我们需要在编程过程中需要替换函数的对象上下文(Function Context),call就是不错的选择。
你可以试着把FunctionContextdemo例子修改如下,再看看是什么结果:
var changed={ item:"banana", act: "eating" };
var original={item: "chair",act: "sitting in"};
function ask(){
return "who's been "+this.act+" my "+this.item;
}
alert("Original : " + ask.call(original));
alert("changed: " + ask.call(changed));
2)javascript如何利用call来模拟面向对象中的继承的,而且可以实现多重继承
// 多重继承
function base1() {
this.member = " base1_Member";
this.showSelf = function() {
window.alert(this.member);
}
}
function base2() {
this.person = " base2_Member";
this.act = " is dancing happily";
this.showAction = function() {
window.alert(this.person + this.act);
}
}
function extend() {
base1.call(this);
base2.call(this);
}
window.onload=function(){
var demo = new extend();
demo.showSelf();
demo.showAction();
}
但仔细深入看看,这样的继承是有问题的,直接在类函数体里面定义成员方法,将导致每个实例都有副本,重复占用了内存。
最为优雅简洁的方式应该算是基于原型(prototype)继承。
3)接下来我们再次来看看javascript框架prototype里是如何利用apply来创建一个定义类的模式:
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
};
解析:
从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数,如此就可以实现prototype中的类创建模式.目的是规定如此一个类创建模式,让类的初始化函数名一定是initialize(),而this.initialize.apply(this, arguments);(令人有些费解)则是保证initialize一定会在类的实例创建后调用,既方便管理又体现Object-Oriented的思想。
注意: 里边的this其实是同一对象,即相当于类本身调用自己的构造函数来创建Class对象! 因为apply方法的第二个参数本身要求是一个数组,所以传递给该函数的参数也传递给类的initialize方法,如果直接写为 this.initialize(arguments); 则所有的参数是作为一个数组传递给了initialize构造函数。
var vehicle=Class.create();
vehicle.prototype={
initialize:function(type){
this.type=type;
}
showSelf:function(){
alert("this vehicle is "+ this.type);
}
}
var moto=new vehicle("Moto");
moto.showSelf();
4) 活用apply(javascript框架prototype的事件绑定):
Function.prototype.bind = function() {
var __method = this;
var args = $A(arguments);
var object = args.shift();
return function() {
// 调用函数的apply方法执行函数, 其中的object为目标对象, args为bind方法中的参数列表(除了第一个参数以外的参数构成的数组)
return __method.apply(object, args.concat($A(arguments)));// 事实上, 这里的$A(arguments)一定是一个空数组
}
}
代码解析:
该bind用途在于将某个函数绑定到特定的函数去执行,
a) var __method = this;这首先把Function Context重新赋值到一个本地变量,使得在Closure(这是一个javascript的特性,可解释为"闭包")中都能访问到,如此在下边就可以方便获取了。它实质就是bind方法的调用者, 是一个函数对象。
b) var args = $A(arguments);这里因为arguments本就是一个类数组的对象,通过$A(arguments)将传入到bind方法的参数都转化为array.
c) var object = args.shift();通过截取args的第一个参数获取Target Object(目标对象),此时args为除了第一个参数以外的参数构成的数组(array)
d) 这是最关键的一步,返回一个新的函数对象(不带有任何的参数的函数),在此通过apply把__method(bind方法的调用者)绑定到Target Object(目标对象),并给与除了Target Object(目标对象)之外的所有参数构成的数组args.concat($A(arguments)),最终Target Object(目标对象)就可执行__method了。
如此费劲周折的绑定某一个函数所换来的优势是,从此你不需要顾及Function Context的混乱所带来的额外顾虑。
分享到:
相关推荐
javascript callApply代码示例
JavaScript中call与apply方法
### 理解JavaScript中的`caller`, `callee`, `call`, `apply` #### Arguments对象:JavaScript函数调用的参数管理器 在JavaScript中,每个函数都有一个隐含参数`arguments`,它允许开发者访问传递给函数的所有参数...
在JavaScript中,`call`和`apply`是两个非常重要的方法,它们都用于改变函数调用时的上下文(即`this`的值),并且可以灵活地传递参数。本篇文章将深入探讨这两个方法的用法、区别以及实际应用场景。 `call`方法...
在JavaScript中,`call` 和 `apply` 是两种非常重要的函数调用方式,它们都用于改变函数执行时的上下文,即`this`的指向。本文将深入探讨这两种方法的用法及其在实际编程中的应用。 ### 1. `call` 的基本用法 `...
在JavaScript编程中,`call` 和 `apply` 是两种非常重要的方法,它们允许我们改变函数内部 `this` 的指向。这两个方法在处理事件绑定时尤其关键,因为默认情况下,当JavaScript对象的方法被绑定到DOM事件上,事件...
在JavaScript中,`call()`, `apply()`, 和 `bind()` 是三个非常重要的函数,它们都与函数调用有关,但各自有不同的应用场景。本文将深入探讨这三个函数的实现原理及其使用方式。 首先,`call()` 函数允许我们调用一...
JavaScript中的`call`和`apply`是两种非常关键的方法,它们允许我们改变函数内部`this`的指向,同时也为实现模拟继承提供了可能。虽然JavaScript不直接支持类继承,但通过`call`和`apply`,我们可以实现类似的效果。...
淡淡简单描述javascript中方法apply和call
这篇文章将深入探讨四个关键概念:caller、callee、call和apply,它们都是JavaScript函数操作的核心部分,对于理解和使用高级JavaScript编程至关重要。 首先,我们来了解`caller`和`callee`。在JavaScript的函数...
call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.
call apply bind 的 作用 都是用来改变this的指向,在平时工作过程中,除了实现对象的继承,在写一些基础类,或者公用库方法的时候会用到它们,其他时候 call 和 apply 的应用场景并不多。 在React中bind常用来绑定...
1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为方法的属性,那它们的使用...
本文针对JavaScript中三个重要的函数方法——call、apply和bind,进行详尽的分析,并在文章的结尾部分对这三个方法之间的联系和区别进行了概括,以便于读者更深入地理解它们的用途和应用场景。 首先,我们来探讨...
### JavaScript中的apply与call用法详解 #### 一、引言 在JavaScript中,`apply`与`call`是两个非常重要的函数,它们都属于`Function.prototype`的一部分,因此每一个函数对象都拥有这两个方法。这两个方法的主要...
当`call`和`apply`的第一个参数为`null`或`undefined`时,`this`将默认指向全局对象(在浏览器环境中是`window`,在Node.js环境中是`global`)。例如: ```javascript var a = 10, b = 20; function testFun() { ...
JavaScript中的`callee`、`call`和`apply`都是与函数有关的重要概念,它们提供了不同的方式来处理函数调用和上下文。以下是这三个特性的详细解释: **arguments.callee** `arguments.callee`是一个在函数内部可以...
JavaScript 中的 call、apply、bind 方法详解 JavaScript 中的 call、apply、bind 方法是 Function 对象自带的三个方法,这三个方法的主要作用是转变函数中的 this 指向,从而可以达到“接花移木”的效果。下面将对...
JavaScript中的`call`和`apply`是两种非常重要的方法,它们都用于改变函数内部`this`的指向,并执行该函数。这两个方法都是Function对象的原型方法,因此所有的函数都具备`call`和`apply`。 1. `call`方法: - `...
JS中的call、apply、bind方法详解 随着JavaScript的发展,函数调用对象的改变变得越来越重要。在JavaScript中,call、apply、bind三个方法都是函数对象的方法,它们的作用都是改变函数的调用对象。下面,我们将详细...