javascript必知之prototype

<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>javascript必知会之prototype</title>
    <script type="text/javascript" language="javascript">
        
        function foo(a, b, c) {
            return a * b * c;
        }
        alert(foo.length);
        alert(typeof foo.constructor);
        alert(typeof foo.call);
        alert(typeof foo.apply);
        alert(typeof foo.prototype);
        /*
            对于上面的代码,用浏览器运行后你会发现:
                1、length提供的是函数的参数个数
                2、prototype是一个object
                3、其他三个都是function
            而对于任何函数的声明,他都将会具有上面所述的5个property(方法或者属性)
            下面主要看prototy
        */
        function Person(name, gender) {
            this.name = name;
            this.gender = gender;
            this.whoAreYou = function() {//这个所谓的closure;内部函数可以访问外部函数变量
                var res = "I'm " + this.name + " and I'm a " + this.gender;
                return res;
            };
        }
        //那么由Person创建的对象便有了下面几个属性
        Person.prototype.age = 24;
        Person.prototype.getAge = function() {
            return this.age;
        };
        flag = true;
        if (flag) {
            var fun = new Person("Tower", "male");
            alert(fun.name);
            alert(fun.gender);
            alert(fun.whoAreYou());
            alert(fun.getAge());
        }
        Person.prototype.salary = 10000;
        Person.prototype.getSalary = function() {
            return this.name + "can earn about " + this.salary + " RMB each month.";
        };
        /*
            下面就是最神奇的地方了,我们改变了Person的prototype,而这个改变是在创建fun之后
            而这个改变使得fun也具有了相同属性和方法
            继承的意味即此
        */
        if (flag) {
            alert(fun.getSalary());
            alert(fun.constructor.prototype.age);//而这个相当于你直接调用了Person.protype.age
            alert(Person.prototype.age);
        }
        /*
            从上面的示例中我们可以发现,对于prototype的方法或者属性,我们可以 动态地 增加,而由其创建的 对象 自动
            会 继承 相关的方法和属性
            
            另外,每个对象都一个constructor属性,用于指向创建其函数的对象,如上例中的fun.constructor指向的就是 Person
            
            那么一个疑问就自然产生了,"函数对象中自身的方法和属性与prototype声明的对象有什么差别?"
            
            有下面几个差别:
                1、自身声明的方法和属性是 静态的,也就是说你在声明后,试图再去增加新的方法或者修改已有的方法,并不会对由其创建的对象产生影响,也即继承失败。
                2、而prototype可以动态的增加新的方法或者修改已有的方法,从而是动态的,一旦父函数对象声明了相关的prototype属性,由其创建的对象会自动继承这些prototype的属性
            
            继续上面的例子
        */
        flag = true;
        //函数内部声明的方法是静态的,无法传递的
        Person.school = "ISCAS";
        Person.whoAreYou = function() {
            return "zhutao";
        }; //动态更改声明期的方法,并不会影响其创建的方法,即所谓的静态
        if (flag) {
            alert(Person.school);//输出"ISCAS"
            alert(fun.school);//输出"undefined"
            alert(Person.whoAreYou());//zhutao
            alert(fun.whoAreYou());//I'm Tower and I'm a male.
        }
        Person.prototype.getSalary = function() {
            return "I can earn 1000000USD";
        };
        if (flag) {
            alert(fun.getSalary());//已经集成了改变,即所谓的动态
        }
        /* 
            既然有函数对象本身的属性,也有prototype的属性,那么是由其创建的对象是如何搜索相应的属性呢?
            基本是按照下面的流程和顺序来经行的。
                1、先去搜索函数对象本身的属性,若果找到立即执行
                2、如果1没有找到,则会去搜索prototype属性,有2中结果,找到的直接执行,负责积雪搜索父对象的父对象的prototype,知道找到
                    或者达到prototype chain的结尾(结尾会是objec对象)
            上面的也回答如果函数对象本身的属性与prototype属性相同(重名)时的解决方式,函数本身的对象优先
            
            再看一个多重prototype链的例子
        */
        function Employee(neme) {
            this.name = "";
            this.dept = "general";
            this.gender = "unknown";
        }
        function WorkerBee() {
            this.projects = [];
            this.hasCar = false;
        }
        WorkerBee.prototype = new Employee; //第一层prototype链
        function Engineer() {
            this.dept = "enginner"; //覆盖了“父对象”
            this.language = "javascript";
        }
        Engineer.prototype = new WorkerBee; //第二层prototype链
        var jay = new Engineer("Jay");
        if (flag) {
            alert(jay.dept);//engineer,找到的是自己的属性
            alert(jay.hasCar);//flase,搜到的是自己上一层的属性
            alert(jay.gender);//unknown,搜到的是自己上二层的属性
        }
    </script>
</head>
<body>
</body>
</html>

posted @ 2011-04-27 11:16  ╰☆Everytime I try to flying  阅读(209)  评论(0编辑  收藏  举报