首頁 >web前端 >js教程 >js繼承方法有什麼? js的繼承的兩種方法介紹(附程式碼)

js繼承方法有什麼? js的繼承的兩種方法介紹(附程式碼)

不言
不言原創
2018-08-07 17:49:361424瀏覽

js的繼承與java這種傳統的繼承不一樣,js是基於原型鏈的繼承。 JavaScript的繼承可以分為兩類:基於物件的繼承和基於型別的繼承,下面我們就來具體看看js的繼承。

基於js物件的繼承
基於物件的繼承也叫原型繼承。我們知道透過JavaScript字面量建立的物件都會連接到Object.prototype,因此我們用Object.prototype來實現繼承。本質上是摒棄類,不呼叫建構函數,而是用Object.create(),直接讓新物件繼承舊物件的屬性。例如:

var person = {
    name: "Jack",
    getName: function () { return this.name; }
}
var p1 = Object.create(person);
console.log(p1.getName());    //Jack

程式碼很簡單,person有一個屬性和一個方法。物件p1透過Object.create()來繼承,第一個參數prototype指向person的prototype,這樣物件p1就繼承了person的屬性和方法。
Object.create()也可以指定第二個參數,也就是資料屬性,將其加入新物件中。資料屬性可設4個描述符value, writable,enumerable,configurable 。後3個看名字也能猜出意思,不指定的話預設為false。因為和本篇關係不大,就不離題了,只看看設定value的情況:

var p2 = Object.create(person, {
    name: {
        value: "Zhang"
    }
});
console.log(p2.getName());    //Zhang

用Object.create()相當於創建了一個全新的對象,你可以給該對象任意新增,重載它的屬性與方法:

var person = {
    name: "Jack",
    getName: function () { return this.name; },
    getAge: function() { return this.age; } //注意并没有age这个成员变量,依赖子类实现
}

var p3 = Object.create(person);
p3.name = 'Rose';
p3.age = 17;
p3.location = '上海';
p3.getLocation = function() { return this.location; }

console.log(p3.getName());    //Rose
console.log(p3.getAge());     //17
console.log(p3.getLocation());    //上海

在person中並沒有age這個屬性,因此你呼叫person.getAge();會得到undefined。但在物件p3裡新定義了age這個屬性,於是就能正確地呼叫基底類別的getAge方法。另外子類別重載了name的值,且新定義了location屬性和getLocation方法。結果如上所示,不贅述。

基於js類別的繼承
基於類型的繼承是透過建構函式依賴原型的繼承,而不是依賴物件。例如:

function Person(name) {
    this.name = name;
    this.getName = function () { return this.name; };  
}
function Student(name, age) {
    Person.call(this, name);
    this.age = age;
    this.getAge = function () { return this.age; }; 
}
Student.prototype = new Person();    //需要通过new来访问基类的构造函数

var p = new Person('Cathy');
var s = new Student('Bill', 23);

console.log(p.getName());    //Cathy
console.log(s.getName());    //Bill
console.log(s.getAge());     //23

Student繼承自Person。雖然name是在基底類別Person裡被定義的,但用new呼叫Person的建構子後,this會被綁定到子類別Student物件上,因此name最終是定義在子類別Student物件上的。結果如上所示,不贅述。
保護隱私權
之所以定義getName,getAge等方法就是不想讓使用者直接存取name,age等屬性。可惜上面兩種繼承無法保護隱私,皆可像p.name,p.age這樣直接存取屬性。如果認為這些屬性的隱私非常重要,希望模擬出OO語言中private屬性的效果,可以用函數模組化。
所謂函數模組化,本質上就是在函數內新建一個對象,新對象的方法裡使用參數對象的屬性,然後將新對象返回。此時新物件裡是沒有參數物件的屬性的,達到了保護隱私的目的。程式碼如下:

var person = function(spec) {
    var that = {};        //新对象
    that.getName = function () { return spec.name; };  //使用参数的属性
    that.getAge = function() { return spec.age; };  //使用参数的属性
    return that;        //返回新对象
}

var p4 = person({name: 'Jane', age: 20});

console.log(p4.name);    //undefined
console.log(p4.age);     //undefined
console.log(p4.getName());    //Jane
console.log(p4.getAge());     //20

因為函數person回傳的是新物件that,而that裡並沒有name和age屬性,因此直接存取會得到undefined。只能透過that暴露出的兩個介面來取得name和age。
進一步實現多層繼承也非常方便,效果如下,不贅述:

var student = function(spec) {
    var that = person(spec);        //新对象继承自person
    that.getRole = function() { return 'student'; };  //新对象增加方法
    that.getInfo = function() {
        return spec.name + ' ' + spec.age + ' ' + that.getRole();
    };
    return that;    //返回新对象
};

var p5 = student({name:'Andy', age:12});

console.log(p5.name);       //undefined
console.log(p5.getName());  //Andy
console.log(p5.getRole());  //student
console.log(p5.getInfo());  //Andy 12 student

相關文章推薦:

JS繼承--原型鏈繼承和類別繼承_基礎知識

JS實作繼承的幾種方式

JavaScript中的繼承之類繼承_javascript技巧

以上是js繼承方法有什麼? js的繼承的兩種方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn