Javascript函数深入研究:函数中判断自己是以哪种形式被调用的,是A(),还是new A()或者其它?(2011-01-24)

发布时间 2011-01-24 19:52:00

假设有一个函数A是这样的:

function A(){  }

可能的调用方式有:

new A();
A();
A.a=A; A.a();
A.prototype.b=A; b=new A(); b.b();
A.prototype.c=A; A.prototype.c();
d=new A(); d.d=A; d.d();
A.apply(new A());
A.call(new A());
A.apply(A);
A.call(A);

等。

本文通过一个比较全面的示例,展示如何在函数定义中对各种情形进行判断。

需要指出的是,有些情况是等效的,运行时无法进行区分。

主要用到的特性有:callee, constructor, hasOwnProperty, instanceof, prototype

 

先看看我的示例文档的输出结果:

function Person(n,a){
    //......
}

 

Person();
1.上面是普通函数调用



Person.prototype.aa = Person;
var p = new Person();
2.上面是new Person() 调用
p.aa();
3.上面是 原型方法aa 调用
Person.prototype.aa();
4.上面是“Person.prototype.***”调用


Person.call(document);
5.上面是普通函数调用
Person.call(Person);
6.上面是普通函数调用
Person.call(p);
7.上面是 原型方法aa 调用


Person.prototype = { };
var p = new Person();
8.上面是new Person() 调用
p.aa = Person;
p.aa();
9.上面是 扩展属性aa 调用


Person.prototype = {aa:Person};
var p = new Person();
10.上面是new Person() 调用
p.aa();
11.上面是 原型方法aa★★ 调用
Person.prototype.aa();
12.上面是“Person.prototype.***”调用▲▲▲


var p = new Person();
13.上面是new Person() 调用
p.fn = Person;
p.haha = Person;
p.fn();
14.上面可能是 原型方法bb★★原型方法aa★★扩展属性fn扩展属性haha 调用


Person.hello = Person;
Person.hello();
15.上面是普通函数调用
Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();
16.上面是普通函数调用
new Person.hello();
17.上面是new Person() 调用
new Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();
18.上面是new Person() 调用


eval(Person.toString().replace('Person','B'));
new B();
19.上面是new B() 调用

源代码:

var i=1;
function echo(s){
    document.writeln('<br /><span style="background-color:#FFDFFF; margin-left:40px;" mce_style="background-color:#FFDFFF; margin-left:40px;">'+s+'</span>');
}
function Person(){
    var className = arguments.callee.toString().substr(9).match(/[^/s/(]+/)[0];
    var s='',sureNew=false,surePrototype=false;
    if(this instanceof arguments.callee){
        if(!this.__newed__){
            echo((i++)+'.上面是<b>new '+className+'()</b>调用');
            this.__newed__=true;
        }else{
            //obj.method() or obj.property()
            var pbs=[],bo=false,bp=false;
            for(v in this){
                if(this[v]==arguments.callee){
                    if(this.hasOwnProperty(v)){
                        pbs.push('<font color="green">扩展属性'+v+'</font>');
                        bo=true;
                    }else if(this.constructor.prototype.hasOwnProperty(v)){
                        pbs.push('<font color="blue">原型方法'+v+'</font>');
                        bp=true;
                    }else if(arguments.callee.prototype.hasOwnProperty(v)){
                        pbs.push('<font color="blue">原型方法'+v+'★★</font>');
                        bp=true;
                    }
                }
            }
            if(pbs.length==0){
                echo((i++)+'.<font color="red">见鬼了★★★★★★★★</font>'); //不可能出现
            }else if(pbs.length==1){
                echo((i++)+'.上面是 '+ pbs[0]+' 调用');
            }else{
                echo((i++)+'.上面可能是 '+ pbs.join(' 或 ')+' 调用');
            }
        }
    }else{
        if(this.constructor === arguments.callee){
            echo((i++)+'.上面是 '+className+'.prototype.*** 调用');
        }else{
            if(this.constructor === Object){
                echo((i++)+'.上面是 '+className+'.prototype.*** 调用▲▲▲');
            }else{
                echo((i++)+'.上面是普通函数调用');
            }
        }
    }
}

document.writeln('function Person(n,a){<br>    //......<br>}');
document.writeln('<br><hr>');
document.writeln('<br>'+"Person();");
Person();

document.writeln('<br><hr>');
document.writeln('<br>'+"Person.prototype.aa = Person;");
document.writeln('<br>'+"var p = new Person();");
Person.prototype.aa = Person;
var p = new Person();

document.writeln('<br>'+"p.aa();");
p.aa();

document.writeln('<br>'+"Person.prototype.aa();");
Person.prototype.aa();

document.writeln('<br><hr>');
document.writeln('<br>'+"Person.call(document);");
Person.call(document);

document.writeln('<br>'+"Person.call(Person);");
Person.call(Person);

document.writeln('<br>'+"Person.call(p);");
Person.call(p);

document.writeln('<br><hr>');
document.writeln('<br>'+"Person.prototype = { };");
document.writeln('<br>'+"var p = new Person();");
//设置Person.prototype.*** = ***;后this.constructor“不变”
//设置了Person.prototype = {...};后this.constructor“会改变”
Person.prototype = {};
var p = new Person();

document.writeln('<br>'+"p.aa = Person;");
document.writeln('<br>'+"p.aa();");
p.aa = Person;
p.aa();

document.writeln('<br><hr>');
document.writeln('<br>'+"Person.prototype = {aa:Person};");
document.writeln('<br>'+"var p = new Person();");
Person.prototype = {aa:Person};
var p = new Person();

document.writeln('<br>'+"p.aa();");
p.aa();

document.writeln('<br>'+"Person.prototype.aa();");
Person.prototype.aa();

document.writeln('<br><hr>');
document.writeln('<br>'+"var p = new Person();");
var p = new Person();

document.writeln('<br>'+"p.fn = Person;");
document.writeln('<br>'+"p.haha = Person;");
document.writeln('<br>'+"p.fn();");
p.fn = Person;
p.haha = Person;
Person.prototype.bb = Person;
p.fn();

document.writeln('<br><hr>');
document.writeln('<br>'+"Person.hello = Person;");
document.writeln('<br>'+"Person.hello();");
Person.hello = Person;
Person.hello();

document.writeln('<br>'+"Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();");
Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();

document.writeln('<br>'+"new Person.hello();");
new Person.hello();

document.writeln('<br>'+"new Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();");
new Person.hello.hello.hello.hello.hello.hello.hello.hello.hello();

document.writeln('<br><hr>');
document.writeln('<br>'+"eval(Person.toString().replace('Person','B'));");
document.writeln('<br>'+"new B();");
eval(Person.toString().replace('Person','B'));
new B();
document.writeln('<br><hr>');
posted @ 2022-11-23 21:10  IginCui  阅读(56)  评论(0)    收藏  举报