我们知道面向对象有继承、封装、多态三种特征。那javascript这种语言其实是一种可变参,并不能像java那样实现多态。例如下面这种情况:
从上面的例子可以看出在javascript中不能有两个相同名字的函数。
那么怎么实现上面的功能呢,在javascript中提供一个arguments这样的一个对象,下面通过一个例子来具体看看argumetns对象
那么从上面的例子我们可以看出javascript函数的参数是不固定的,传入的参数可以根据arguments对象的下标去获取,因此我们可以通过arguments对象变相实现多态。
下面的一个例子用arguments对象来模拟实现array对象的通过下标来访问数组元素
上面的例子中用到this关键字,这个回头我们会讲到。
arguments对象虽然可以通过下标访问传出的参数,但它并非是一个数组对象。
arguments对象有一个callee方法。
因此我们可以打印出callee方法这个函数体看看是什么
从上面这个例子可以看出arguments.callee方法打印的就是这个函数体的本身,因此我们可以利用这个特点去实现递归的功能。
下面是用不同的方式去实现n的阶层的功能。
第一种:函数的方式
第二种:递归的方式
因为arguments对象的callee方法返回的就是调用函数的本身,因此我们可以对第二种方式进行改造一下
第三种:arguments.callee的方式
这种方式的好处是当方法名改动了,我们不用改动方法体里面的调用自身的函数名
讲到callee方法,就要说到跟callee非常相似的方法叫caller方法。当然这个caller方法并不是arguments对象的方法,而是function对象的方法。
因此function对象的caller方法本身就是调用该函数的方法
上面javascript代码也可以进一步改造成下面的形式:
//这个函数永远都不会执行,会被下面的demo方法覆盖
function demo(a,b){
alert(a);
alert(b);
}
function demo(a){
alert(a);
}
//会打印1,2并不会打印出来,由此可看出第一个demo方法并未执行
demo(1,2);
从上面的例子可以看出在javascript中不能有两个相同名字的函数。
那么怎么实现上面的功能呢,在javascript中提供一个arguments这样的一个对象,下面通过一个例子来具体看看argumetns对象
function demo(a){
for(var i=0;i<arguments.length;i++){
alert(arguments[i]);
}
}
//弹出1,2
demo(1,2);
//弹出1,2,3
demo(1,2,3);
那么从上面的例子我们可以看出javascript函数的参数是不固定的,传入的参数可以根据arguments对象的下标去获取,因此我们可以通过arguments对象变相实现多态。
下面的一个例子用arguments对象来模拟实现array对象的通过下标来访问数组元素
function myArray(){
for(var i =0;i<arguments.length;i++){
this[i] = arguments[i];
}
}
var a = new myArray("aa","bb","cc");
//打印bb
alert(a[1]);
上面的例子中用到this关键字,这个回头我们会讲到。
arguments对象虽然可以通过下标访问传出的参数,但它并非是一个数组对象。
function demo(){
var a = [];
alert(arguments instanceof Array); //false
alert(a instanceof Array); //true
}
demo();
arguments对象有一个callee方法。
function fun(){
alert(typeof arguments.callee); //打印function
}
fun();
因此我们可以打印出callee方法这个函数体看看是什么
function fun(){
alert(arguments.callee);//打印这个函数体本身
}
fun();
从上面这个例子可以看出arguments.callee方法打印的就是这个函数体的本身,因此我们可以利用这个特点去实现递归的功能。
下面是用不同的方式去实现n的阶层的功能。
第一种:函数的方式
function fun(n){
var result = i =1;
for(;i<n;i++){
result = result+result*i;
}
return result;
}
var a = fun(5);
alert(a);
第二种:递归的方式
function fun(n){
return n?n*fun(n-1):1;
}
var a = fun(5);
alert(a);
因为arguments对象的callee方法返回的就是调用函数的本身,因此我们可以对第二种方式进行改造一下
第三种:arguments.callee的方式
function fun(n){
//如果true就执行callee方法
return n?n*arguments.callee(n-1):1;
}
var a = fun(5);
alert(a);
这种方式的好处是当方法名改动了,我们不用改动方法体里面的调用自身的函数名
讲到callee方法,就要说到跟callee非常相似的方法叫caller方法。当然这个caller方法并不是arguments对象的方法,而是function对象的方法。
function fun(a,b,c){
alert(fun.caller);//打印出callother方法的函数体
}
function callother(){
fun(1,2);
}
callother();
因此function对象的caller方法本身就是调用该函数的方法
上面javascript代码也可以进一步改造成下面的形式:
function fun(a,b,c){
alert(arguments.callee.caller);//打印callother方法的函数体
}
function callother(){
fun(1,2);
}
callother();