JavaScript的oop中的apply,call
先明确一点,以下部分涉及到function对象和object对象.
当有一个方法或对象,想给另一个方法使用,可以使用以下的方法,按照这个原理实现JS的继承(可以实现多个父类继承,很多语言都做不到,JS强吧.)
阅读前需要理解的:
JS中 没有new 的对象在对象里的this是不存在的
例如:
function a(){
this.b="hi";
this.c=function(){alert('hi');}
}
alert(a.b);//out undefined
try{
a.c();
}catch(e){
alert(e->getmessage());//有输出
}
var a =new a();
alert(a.b);//out hi
a.c();//out hi
如何添加JS的静态属性或方法呢,答案如下
a.b="hi";
a.c=function(){alert("hi");}
在对象里的this只有在new实例的时候才有用,因为this表示对象本身,而不是function本身
相对于静态的,对对象添加属性或方法也可以在类的外面进行:prototype关键字
以下两个相同:
this.b = function(){
alert("hi");
}
}
function c(){
this.b="good";
}
c.prototype.b=function(){
alert("hi");
}
看明白上面的在看下面的,免得理解错误~
call方法的官方解释为:
调用一个对象的一个方法,以另一个对象替换当前对象。
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数
thisObj
可选项。将被用作当前对象的对象。
arg1, arg2, , argN
可选项。将被传递方法参数序列。
说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
====================================================
apply方法的官方解释为:
应用某一对象的一个方法,用另一个对象替换当前对象。
apply([thisObj[,argArray]])
参数
thisObj
可选项。将被用作当前对象的对象。
argArray
可选项。将被传递给该函数的参数数组。
说明
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
从上面官方的介绍可以看出,两者实现的功能是完全一样的,只是参数传递方式不一样,call是将各个参数以“,”隔开,而apply是将所有参数组成一个数组进行传递。
简单的说就是把obj1的方法放到obj2上使用,后面的argument1..这些做为参数传入.
如果还不给力,看下例子:
alert(this.a);
}
function b(){
this.a="hi";
f.call(this);
}
new b();//alert hi
同理想把一个对象里的方法用到令一个对象可以如下:
this.b=function(){
alert(this.a);
}
}
function b(){
this.a="hi";
}
var t=new b();
var n=new f();
n.b.call(t);//alert hi
如用apply一样的效果
两个区别自己做测试~不解析鸟~
有个要注意的
var a="go";
this.d=function(){
alert(a);//alert go
alert(this.a);
}
}
function b(){
this.a="hi";
}
var t=new b();
var n=new f();
n.d.call(t);
上面的代码会输出go hi
说明代码的运行空间还是在f 函数中,但this已经被替换成 b的实例了
这个要注意下,f里的d方法d并不是完全变为b的方法,只是将f中的方法中的实例换成b的实例,然后在运行f里的d方法,f环境里定义的变量在f里的d是完全可用的,由于f里的d方法的this被b对象替换,所有f里的d方法访问的是b对象来的,但对于b对象而言,并未增加新的方法
通过上面的解释来做继承实现
this.a=v;
}
function b(v){
this.b="test2";
a.apply(this,new Array(v));
//apply意思是将a类里的this用b对象替换,参数传递通过第二个数组参数
}
var c=new b();
alert(c.a);
alert(c.b);
总结出一个方便记忆的方法:可以把apply或call看成的替换,用apply或call的时候的意思是要把当前Function对象里的this(就是对象本身)用指定的对象替换,如果被当前Function对象里有this.a=funtion(){}或this.b="hi",因为调用apply或call的时候在运行该方法,也就等于在指定的对象上增加新的属性或方法(和 指定的对象.a=function(){}或指定的对象.b="hi"的意思一样),从而指定的对象里也就增加了这个方法或属性,如果没有,指定的对象的也就没有新的属性或方法添加,实现继承的原理就是这样的.
call apply 是对Function对象而言,而Object对象本身没有这两个函数,如下例:
this.f=function(){alert("af");}
}
function b(){
}
var oa=new a();
var ob=new b();
oa.call(ob);//错误的~~
ob.f();
从本质上来看apply和call方法只为了实现方法重用,JS的OO还是挺强的~
接着上面的,实现重写:
this.f=function(){
alert("af");
};
this.c=function(){
alert("ac");
}
}
function b(){
a.call(this);
var bf=this.f;
this.f=function(){
bf();//调用父类方法
alert("bf")
};
}
var ob=new b();
ob.f();
ob.c();
实现重载:
function a(){
var _f1=function(v1){
alert(v1);
}
var _f2=function(v1,v2){
alert(v1);
}
this.f=function(){
switch(typeof(arguments[0])){
case 'number':
_f1(arguments[0]);
break;
case 'string':
_f2(arguments[0]);
break;
}
};
}
var oa=new a();
oa.f(1);
oa.f("string");
//示例2:
function a(){
var _f1=function(v1){
alert(v1);
}
var _f2=function(v1,v2){
alert(v1);
alert(v2);
}
this.f=function(){
switch(arguments.length){
case 1:
_f1(arguments[0]);
break;
case 2:
_f2(arguments[0],arguments[0]);
break;
}
};
this.c=function(){
alert("ac");
}
}
var oa=new a();
oa.f(1);
oa.f(1,2);
函数中的caller属性
这个属性在函数体上表示调用该函数的函数代码,如下例
function callerDemo() {
if (callerDemo.caller) {
var a= callerDemo.caller.toString();
alert(a);
} else {
alert("this is a top function");
}
}
function handleCaller() {
callerDemo();
}
handleCaller();
会打印出:
function handleCaller() {
callerDemo();
}
对象:callee
callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用
其中arguments.callee.length是形参长度
普通对象转为函数对象后使用call
(function(){'ddd':'dddd'}).call({})