本文實例講述了JavaScript面向對象繼承原理與實現方法。分享給大家供大家參考,具體如下:
1、構造函數、原型和實例的關系
構造函數有一個原型屬性prototype指向一個原型對象。
原型對象包含一個指向構造函數的指針constructor 。
實例包含一個指向原型對象的內部指針[[prototype]] 。
2、通過原型鏈實現繼承
基本思想:利用原型讓一個引用類型繼承另一個引用類型的屬性和方法,子類型可以訪問超類型的所有屬性和方法。原型鏈的構建是將一個類型的實例賦值給另一個構造函數的原型實現的。實現的本質是重寫原型對象,代之以一個新類型的實例。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
alert("Hello, " + this.name);
}
var person = new Person("Alice");
person.sayHello(); // Hello, Alice
function Student() {
}
Student.prototype = new Person("Bruce");
Student.prototype.id = 16;
Student.prototype.showId = function() {
alert(this.id);
}
var student = new Student();
student.sayHello(); // Hello, Bruce
student.showId(); // 16
注意:不能用對象字面量創建原型方法,這樣會重寫原型鏈,導致繼承無效。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
alert("Hello, " + this.name);
}
var person = new Person("Alice");
person.sayHello(); // Hello, Alice
function Student() {
}
Student.prototype = new Person("Bruce");
Student.prototype.id = 16;
Student.prototype = {
showId: function() {
alert(this.id);
}
};
var student = new Student();
student.sayHello(); // 報錯:student.sayHello is not a function
student.showId(); // 16
student指向Student的原型,Student的原型又指向Person的原型。
student.sayHello()原型鏈搜索機制:
1)搜索student實例中是否有sayHello()
2)搜索Student.prototype是否有sayHello()
3)搜索Person.prototype是否有sayHello()
子類型有時候需要覆蓋超類型的某個方法,或者需要添加超類型中不存在的某個方法。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
alert("Hello, " + this.name);
}
var person = new Person("Alice");
person.sayHello(); // Hello, Alice
function Student() {
}
Student.prototype = new Person("Bruce");
Student.prototype.id = 16;
Student.prototype.showId = function() {
alert(this.id);
}
Student.prototype.sayHello = function() {
alert("Hi, " + this.name);
}
var student = new Student();
student.sayHello(); //Hi, Bruce
student.showId(); // 16
注意:給原型覆蓋或添加方法的代碼一定要放在替換原型的語句之后。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
alert("Hello, " + this.name);
}
var person = new Person("Alice");
person.sayHello(); // Hello, Alice
function Student() {
}
Student.prototype.sayHello = function() {
alert("Hi, " + this.name);
}
Student.prototype = new Person("Bruce");
Student.prototype.id = 16;
Student.prototype.showId = function() {
alert(this.id);
}
var student = new Student();
student.sayHello(); // Hello, Bruce
student.showId(); // 16
確定實例和原型的關系:
(1)instanceof
alert(student instanceof Object); // true alert(student instanceof Student); // true alert(student instanceof Person); // true
(2)isProtptypeOf
alert(Object.prototype.isPrototypeOf(student)); // true alert(Student.prototype.isPrototypeOf(student)); // true alert(Person.prototype.isPrototypeOf(student)); // true
(3)getPrototypeOf
Object.getPrototypeOf(student1) == Student.prototype
使用原型鏈實現繼承的問題:
(1)引用類型的屬性會被實例共享,原型實現繼承時,原型會變成另外一個類型的實例,實例的屬性則變成了現在的原型屬性,從而被共享。
function Person(name, age) {
this.friends = ["Cindy","David"];
}
function Student() {
}
Student.prototype = new Person();
var student1 = new Student();
student1.friends.push("Bruce");
alert(student1.friends); // "Cindy","David","Bruce"
var student2 = new Student();
alert(student1.friends); // "Cindy","David","Bruce"
(2)在創建子類型的實例時,不能向超類型的構造函數中傳遞參數,實際上,應該是沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數。
實際中很少單獨使用原型鏈實現繼承。
3、通過構造函數實現繼承
基本思想:在子類型構造函數的內部調用超類型構造函數。通過使用apply()和call()方法也可以在新創建的對象上執行構造函數。
function Person(name, age) {
this.name = name;
this.age = age;
}
function Student() {
Person.call(this,"Alice",22); // 繼承了構造函數Person,同時還傳遞了參數
this.id = 16; // 實例屬性
}
var student = new Student();
alert(student.name); // "Alice"
alert(student.age); // 22
alert(student.id); // 16
使用構造函數實現繼承的問題:
(1)在超類型的原型中定義的方法,對子類型而言是不可見的,結果所有類型都只能使用構造函數模式。
(2)要想子類能夠訪問超類定義的方法,方法只能在構造函數中定義,但方法在構造函數中定義時,函數復用無從談起。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.showName = function() {
alert(this.name);
};
function Student() {
Person.call(this,"Alice",22);
this.id = 16;
}
var student = new Student();
alert(student.showName()); // 報錯:student.showName is not a function
實際中很少單獨使用使用構造函數實現繼承。
4、組合使用原型鏈和構造函數實現繼承
思路:使用原型鏈繼承共享的屬性和方法,使用構造函數繼承實例屬性。
效果:既通過在原型上定義方法實現了函數復用,又能夠保證每個實例都有自己的屬性。
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ["Cindy","David"];
}
Person.prototype.sayHello = function() {
alert("Hello, " + this.name);
}
function Student(name, age, id) {
Person.call(this, name, age);
this.id = id;
}
Student.prototype = new Person();
Student.prototype.showId = function() {
alert(this.id);
}
var student1 = new Student("Alice", 22, 16);
student1.friends.push("Emy");
alert(student1.friends); // "Cindy","David","Emy"
student1.sayHello(); // Hello, Alice
student1.showId(); // 16
var student2 = new Student("Bruce", 23, 17);
alert(student2.friends); // "Cindy","David"
student2.sayHello(); // Hello, Bruce
student2.showId(); // 17
更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。