- 浏览: 45714 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
天使建站:
这里这篇文章更详细 还有完整的实例演示:js跳出循环:brea ...
js学习break、continue、return、witch等语句 -
FX夜归人:
var sm = new Ext.grid.CheckboxS ...
Ext.grid.CheckboxSelectionModel 只能选一行,不能全选和多选
因为继续研究Ajax Framework的原因,更多的接触了call和apply。
故再次论述call和apply,
1)无疑关于call,最简单的解释就是:把隐藏的第一个参数显示化。因为通常一个函数(Function)的调用,会有一个额外的隐藏参数,就是函数(Function)所属的对象(如果没有所特指,则为global(如window)对象),在函数内你可用this关键字访问之。
从call的构造式 -- call(thisArg[,arg1,arg2…] ]);可看出
call(apply)方法可将一个函数的对象上下文(Function Context)从初始的上下文改变为由 thisObj 指定的新对象,这就是利用call(apply)的最大优势。说到此,我们不妨提提所谓的Function Context到底是为何物。先看看下面FunctionContextDemo:
解析上述代码:
最初存在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例子修改如下,再看看是什么结果:
2)javascript如何利用call来模拟面向对象中的继承的,而且可以实现多重继承
但仔细深入看看,这样的继承是有问题的,直接在类函数体里面定义成员方法,将导致每个实例都有副本,重复占用了内存。
最为优雅简洁的方式应该算是基于原型(prototype)继承。
3)接下来我们再次来看看javascript框架prototype里是如何利用apply来创建一个定义类的模式:
解析:
从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数,如此就可以实现prototype中的类创建模式.目的是规定如此一个类创建模式,让类的初始化函数名一定是initialize(),而this.initialize.apply(this, arguments);(令人有些费解)则是保证initialize一定会在类的实例创建后调用,既方便管理又体现Object-Oriented的思想。
注意: 里边的this其实是同一对象,即相当于类本身调用自己的构造函数来创建Class对象! 因为apply方法的第二个参数本身要求是一个数组,所以传递给该函数的参数也传递给类的initialize方法,如果直接写为 this.initialize(arguments); 则所有的参数是作为一个数组传递给了initialize构造函数。
4) 活用apply(javascript框架prototype的事件绑定):
代码解析:
该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的混乱所带来的额外顾虑。
转自:http://www.cnblogs.com/sunwangji/archive/2007/06/26/791428.html
故再次论述call和apply,
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的混乱所带来的额外顾虑。
转自:http://www.cnblogs.com/sunwangji/archive/2007/06/26/791428.html
发表评论
-
DOM扩展
2014-02-24 15:06 757对DOM的两个主要的扩展 ... -
COM对象
2014-02-23 15:51 4581、COM COM:The Component Object ... -
客户端检测
2014-02-20 14:12 3258客户端检测是javascript开发中最具争议的一个话题。由于 ... -
javascript基础知识(二)
2014-02-17 11:30 0函数表达式 定义函数的方式有两种,一种是函数声明,另一种就是 ... -
javascript基础知识(一)
2014-02-14 10:33 5401、Boolean类型 var flaseObject = n ... -
鼠标定位
2013-11-25 15:10 593当我们单击或移动鼠标时,一般都需要获得鼠标位置,其位置可分为C ... -
js 添加事件 attachEvent 和 addEventListener 的用法
2013-11-25 10:42 708一般我们在JS中添加事件,是这样子的 1 obj.onclic ... -
JavaScript数组
2013-11-21 11:05 506JavaScript数组是有序集合,它包含堆栈、队列等数 ... -
全面理解javascript的caller,callee,call,apply概念(修改版)
2013-11-11 15:31 877在提到上述的概念之前 ... -
IE下使用excanvas.js的注意事项
2013-10-16 09:53 1281下载网址:http://code.google.com/p/e ... -
JS判断浏览器类型方法
2013-10-16 09:42 2209方法一: 2009-05-29 23:01 ... -
网站如何做到 jQuery-free?
2013-06-14 14:45 925本文转载自ITeye新闻月 ... -
js学习break、continue、return、witch等语句
2013-04-25 17:23 20651、break语句 break语句会使运行的程序立刻退出包含在 ... -
js == 与 === 的区别
2013-04-18 17:22 684”==”与”===”是不同 ... -
javascript eval和JSON之间的联系
2012-12-27 13:13 774javascript eval和JSON之间的联系 如果您想 ...
相关推荐
您可以使用 call 和 apply 来执行此操作,如下所示: Array . prototype . map . call ( 'abcdef' , function ( letter ) { return letter . toUpperCase ( ) ;} ) ; // ['A', 'B', 'C', 'D', 'E', 'F'] 如果你经常...
- 在JavaScript中,可以通过构造函数的方式实现继承,即在一个构造函数中调用另一个构造函数,并使用`call()`或`apply()`方法传递上下文。 - ES6引入了`class`关键字来更加直观地实现继承,使用`extends`关键字...
- 使用 `call()` 或 `apply()` 方法可以实现在构造函数中的继承。 - 示例代码中展示了如何使用 `call()` 方法将一个构造函数的属性和方法继承给另一个构造函数的实例。 ```javascript function classA(sstr) { ...
- 申请参与项目:"I am writing to you with the reference to the project that helps the children in poor areas and I want to apply for it." 表明希望参与帮助贫困地区儿童的项目。 - 请求帮助:"I am ...
重写这些函数,开发者需熟悉JavaScript的闭包、函数参数及作用域概念,以及如何通过`Function.prototype.call()`和`Function.prototype.apply()`来改变函数上下文。 3. **对象操作**:如`_.extend()`用于对象合并,...