首頁 > 軟體

js面試題繼承的方法及優缺點解答

2022-09-04 18:03:23

說一說js繼承的方法和優缺點?

要點: 原型鏈繼承、借用建構函式繼承、組合繼承、原型式繼承、寄生式繼承、寄生組合式繼承、ES6 Class

答:

一、原型鏈繼承

缺點:

  • 1.參照型別的屬性被所有範例共用
  • 2.在建立 Child 的範例時,不能向 Parent 傳參
//原型鏈繼承
        function Parent() {
            this.parentPrototype = "parent prototype"
            //驗證這種繼承方法的確定,如果父類別範例中存在一個參照型別的屬性,將會被所有子類共用
            this.parentObj = {
                info: "我是 parent 參照屬性parentObj中的 info"
            }
        }
        function Children() {
        }
        //將Children的原型物件指定為Parent的範例,通過原型鏈,將Parent中的屬性賦值給Children範例
        Children.prototype = new Parent();
        const a = new Children();
        console.log(a.parentPrototype); // parent prototype
        //缺點
        const b = new Children();
        //在a範例中改動繼承的參照屬性
        a.parentObj.info = "我是a範例中 參照屬性parentObj中的 info"
        //b與a範例共用參照屬性
        console.log(b.parentObj.info); // 我是a範例中 參照屬性parentObj中的 info

二、借用建構函式(經典繼承)

優點:

  • 1.避免了參照型別的屬性被所有範例共用
  • 2.可以在 Child 中向 Parent 傳參

缺點:

  • 1.方法都在建構函式中定義,每次建立範例都會建立一遍方法。
function Parent() {
                this.parentPrototype = "parent prototype"
                this.obj = {
                    info: "parent obj info"
                }
                this.fn = function () {
                    console.log("列印功能")
                }
            }
            function Children() {
                Parent.call(this);
            }
            const a = new Children();
            console.log(a.parentPrototype); // parent ptototype
            //缺點 此時Parent()會再次建立一個fn函數,這個是沒有必要的
            const b = new Children();
            a.obj.info = "a obj info";
            //優點 避免了子類範例共用參照屬性
            console.log(b.obj.info) // parent obj info;

三、組合繼承

優點:

  • 1.融合原型鏈繼承和建構函式的優點,是 JavaScript 中最常用的繼承模式。
function Parent() {
                this.parentPrototype = "我是Parent 中的屬性"
            }
            //Parent中的方法,在原型上定義
            Parent.prototype.pFn = function () {
                console.log('我是Parent中的方法');
            }
            function Children() {
                //Parent中的屬性仍然在建構函式中繼承
                Parent.call(this);
            }
            //將Children的原型物件賦值為 Parent範例,這樣Parent中的方法也能夠被Children繼承
            Children.prototype = new Parent();
            const c = new Children();
            console.log(c.parentPrototype); //我是Parent 中的屬性
            c.pFn(); //我是Parent中的方法

四、原型式繼承

缺點: - 1.包含參照型別的屬性值始終都會共用相應的值,這點跟原型鏈繼承一樣。

function objFn(o) {
                o.objFnPrototype = "我是 objFnPrototype"
                function F() {}
                F.prototype = o;
                return new F();
            }
            let a = objFn({
                name: "name1"
            });
            console.log(a.name); //name1
            console.log(a.objFnPrototype); //我是 objFnPrototype

五、寄生式繼承

缺點:

  • 1.跟借用建構函式模式一樣,每次建立物件都會建立一遍方法。
function createObje(obj) {
                let clone = Object.assign(obj); //接受到物件後,原封不動的建立一個新物件
                clone.prototype1 = "我是新增的prototype1"; //在新物件上新增屬性,這就是所謂的寄生
                return clone; //返回新物件
            }
            const parent = {
                parentPrototype: "parentPrototype"
            }
            //c範例,就繼承了parent的所有屬性
            let c = createObje(parent);
            console.log(c.parentPrototype); //parentPrototype

六、寄生組合式繼承

優點:

  • 1.這種方式的高效率體現它只呼叫了一次 Parent 建構函式,並且因此避免了在 Parent.prototype 上面建立不必要的、多餘的屬性。
  • 2.與此同時,原型鏈還能保持不變;
  • 3.因此,還能夠正常使用 instanceof 和 isPrototypeOf。
function inherProto(superType, subType) {
                //拷貝一個超類的原型副本
                let proto = {
                    ...superType.prototype
                };
                //將原型的超類副本作為子類的原型物件,也就是第一種中的原型鏈繼承方式,只不過繼承的是超類原型的副本
                subType.prototype = proto;
                //這一步比較迷,官方的說法是,我們在拷貝超類的原型的時候,拷貝的proto物件,將會丟失預設自己的建構函式,也就是superType,
                //所以我們這裡將它的建構函式補全為subType。貌似不做這一步也沒啥問題,但是缺了點東西可能會有其他的副作用,所以還是補上
                proto.constructor = subType;
            }
            function Super() {
                this.superProto = "super proto";
                this.colors = ["red", "yelloy"];
            }
            function Sub() {
                this.subProto = "sub proto";
                this.name = "sub name";
                //這裡還是借用建構函式的套路
                Super.call(this);
            }
            Super.prototype.getName = function () {
                console.log(this.name);
            }
            //這裡要在定義完Super的屬性後執行,因為繼承的是超類原型的副本,與Super.prototype是兩個物件,在這之後再改變Super.prototype,就已經不會在影響到Sub所繼承的副本超類原型物件了
            inherProto(Super, Sub);
            let a = new Sub();
            console.log(a.getName);

以上就是js面試題繼承的方法及優缺點解答的詳細內容,更多關於js面試題繼承方法優缺點的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com