js中原型鏈和繼承的問題


 

1、當構造函數中包含和原型對象重名的方法和屬性時(構造函數中的會覆蓋原型對象中的方法和屬性)

 1 function Person() {
 2                 this.name="martin";
 3                 this.gun=function () {
 4                     alert("i am a person")
 5                 }
 6             }
 7             Person.prototype.gun=function () {
 8                 alert("biubiu");
 9             }
10 var xiaoGang=new Person();
11 xiaoGang.gun();//輸出i am a person
12       

2、當正常的繼承用法

    function Person() {
                this.name="martin";
                }
            }
            Person.prototype.gun=function () {
                alert("biubiu");
            }
            function Student(){
                this.name="dick";
            }
            Student.prototype=new Person;//Student原型對象作為Person實例擁有Person構造函數所有屬性方法,並包含指向Person原型對象的指針
            }
            var xiaoMing=new Student();
        xiaoMing.gun();//輸出biubiu

原型搜索機制:拿上面的程序舉例,要搜索xiaoMing實例中的gun方法;1、先搜尋xiaoMing實例本身  2、再搜索Student.prototype是否有gun方法 3、最后搜索Person.prototype,發現有所以調用了Person.prototype中的gun方法

針對於整個程序而言gun方法搜索過程:1.xiaoMing實例本身 2、Student構造函數 3、Student.prototype 4、Person構造函數 5、Person.prototype

總結:搜索屬性和方法時從從近到遠搜索,先搜索自身實例,然后搜索離自己最近的子對象,然后父對象(類似於冒泡搜索),同時構造函數中的方法屬性會比其原型對象優先搜索,因為構造函數中的方法屬性會屏蔽(注意和下面覆蓋的區別)原型對象中的方法屬性。

思考:正常的繼承會同時繼承父輩構造函數及其原型對象的方法和屬性,那如果我只要繼承父輩原型對象的方法和屬性怎么辦?

以上面的程序為例:想法:將程序中的Student.prototype=new Person替換成Student.prototype=Person.prototype能否實現

利用程序試驗后得知:改方法可以實現只繼承父輩原型對象的方法屬性,但是因為Person把原型對象地址直接給了Student的原型對象,導致Student和Person原型對象的方法屬性會互相覆蓋,因為他們都指向Person原型對象的地址。

 

 

一般編程用到繼承都用組合繼承,方法繼承用原型鏈繼承,屬性繼承用借用構造函數方法繼承,避免了原型鏈繼承和借用構造函數的缺點(回憶兩種方法各自的缺點),並結合了兩者的優點。

 

    function Person(name){
                this.name=name;
                this.color=["red","green","white"];
            }
            Person.prototype.sayname=function () {
                alert(this.name);
            }
            function Student(name,age) {
                Person.call(this,name);
                this.age=age;
            }
            Student.prototype=new Person;
            Student.prototype.sayAge=function () {
                alert(this.age);
            }
            var xiaoMing=new Student("xiaoMing",23);
            xiaoMing.color.push("black");
            alert(xiaoMing.color);
            xiaoMing.sayname();
            xiaoMing.sayAge();

 

1、原型鏈方法繼承的缺點

  以上面例子為例,

 Student.prototype=new Person;//重點在這一句
這一句就相當於把Student的原型對象變成了Person的一個實例,也相當於創建了Student.prototype.color=["red","green","white"],所以當Student被實例化時,即var xiaoMing=new Student("xiaoMing",23);
Person構造函數中的屬性color會被xiaoMing實例共享,最后導致一改改所有,所以我們屬性繼承不用原型鏈,方法繼承用原型鏈。(詳見Javascript高級編程P167)
2、借用構造函數缺點
因為利用構造函數創建對象,該對象實例化后屬性和方法雖然同名但都是不相等的,因為他們都分屬於不同的實例,調用相同的方法沒必要在不同實例上都創建一遍,所以方法繼承我們一般不用次方法,屬性繼承用借用構造函數方法。

總結:在使用繼承時,對象方法放在原型對象上,屬性放在構造函數里面。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM