JavaScript是一種被廣泛應(yīng)用于Web前端開(kāi)發(fā)的腳本語(yǔ)言,可以用于制作動(dòng)態(tài)網(wǎng)頁(yè)、游戲、應(yīng)用等等。在JavaScript中,繼承是一個(gè)常見(jiàn)的概念,用于實(shí)現(xiàn)代碼的復(fù)用。本文將簡(jiǎn)單介紹JavaScript中的4種繼承方法,以及它們的優(yōu)缺點(diǎn)。
一、原型鏈繼承
最經(jīng)典的JavaScript繼承方法之一,也是最容易理解和使用的,原型鏈繼承簡(jiǎn)單來(lái)說(shuō)就是讓一個(gè)對(duì)象的屬性和方法在其原型對(duì)象上尋找,如果找不到,繼續(xù)往原型對(duì)象的原型對(duì)象尋找,直到找到Object.prototype為止。
舉個(gè)例子,我們有一個(gè)父類構(gòu)造函數(shù):
我們想在Person的基礎(chǔ)上創(chuàng)建一個(gè)子類,可以這樣寫(xiě):
這樣,當(dāng)我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例會(huì)繼承Person的屬性和方法:
原型鏈繼承的優(yōu)點(diǎn)是簡(jiǎn)單易懂,容易實(shí)現(xiàn),但其缺點(diǎn)也十分明顯,即屬性和方法的共享會(huì)導(dǎo)致對(duì)原型對(duì)象的修改影響所有子類實(shí)例。
二、借用構(gòu)造函數(shù)繼承
借用構(gòu)造函數(shù)繼承是另一種比較常見(jiàn)的繼承方法,它不是通過(guò)原型鏈繼承,而是通過(guò)在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)繼承。
我們同樣以Person為父類構(gòu)造函數(shù)為例:
那么我們就可以創(chuàng)建一個(gè)Student子類,并在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù),如下所示:
這樣我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例將只會(huì)繼承父類的屬性和方法,而不會(huì)影響到父類對(duì)象:
借用構(gòu)造函數(shù)繼承的優(yōu)點(diǎn)是可以避免原型鏈繼承中屬性和方法的共享問(wèn)題,但它的缺點(diǎn)也很明顯,即無(wú)法復(fù)用父類的方法。
三、組合繼承
組合繼承是將原型鏈繼承和借用構(gòu)造函數(shù)繼承兩種方法結(jié)合起來(lái)的一種繼承方式,即在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù),同時(shí)讓子類的原型指向父類的實(shí)例。
我們可以同樣的拿Person和Student來(lái)舉例說(shuō)明:
這樣,我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例既能夠復(fù)用父類的方法,又能夠避免原型鏈繼承中對(duì)原型對(duì)象的修改影響所有子類實(shí)例的問(wèn)題:
組合繼承的優(yōu)點(diǎn)是既能夠復(fù)用父類的方法,又能夠避免原型鏈繼承中的問(wèn)題,但它的缺點(diǎn)也十分明顯,即會(huì)調(diào)用兩次父類構(gòu)造函數(shù),一次在繼承prototype的時(shí)候,一次在調(diào)用父類的構(gòu)造函數(shù)時(shí)。
四、原型式繼承
原型式繼承是ES5之前最常用的一種繼承方式,它借助Object.create方法來(lái)實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的繼承,即讓一個(gè)對(duì)象作為另一個(gè)對(duì)象的原型,從而達(dá)到繼承的效果。
我們可以用一個(gè)例子來(lái)解釋原型式繼承:
從上面的例子中可以看出,Object.create方法是一個(gè)非常省事的繼承方式,只要傳遞一個(gè)對(duì)象作為參數(shù)就可以創(chuàng)建出一個(gè)新的對(duì)象,新對(duì)象從原對(duì)象中繼承其屬性和方法。但它的缺點(diǎn)也同樣明顯,即無(wú)法解決引用類型的問(wèn)題。
綜合4種繼承方法的優(yōu)缺點(diǎn),我們可以看出,每種繼承方式都有其適用的場(chǎng)景和注意事項(xiàng)。選擇合適的繼承方式能夠有效地提高代碼的復(fù)用性和可維護(hù)性,避免在代碼實(shí)現(xiàn)中出現(xiàn)另一個(gè)繼承過(guò)程的問(wèn)題。
一、原型鏈繼承
最經(jīng)典的JavaScript繼承方法之一,也是最容易理解和使用的,原型鏈繼承簡(jiǎn)單來(lái)說(shuō)就是讓一個(gè)對(duì)象的屬性和方法在其原型對(duì)象上尋找,如果找不到,繼續(xù)往原型對(duì)象的原型對(duì)象尋找,直到找到Object.prototype為止。
舉個(gè)例子,我們有一個(gè)父類構(gòu)造函數(shù):
<script> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.name + ", and I'm " + this.age + " years old."); } </script>
我們想在Person的基礎(chǔ)上創(chuàng)建一個(gè)子類,可以這樣寫(xiě):
<script> function Student(name, age, grade) { this.grade = grade; } Student.prototype = new Person(); Student.prototype.constructor = Student; </script>
這樣,當(dāng)我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例會(huì)繼承Person的屬性和方法:
<script> var s = new Student("Tom", 18, "Grade 12"); s.sayHello(); // 輸出 "Hello, my name is Tom, and I'm 18 years old." </script>
原型鏈繼承的優(yōu)點(diǎn)是簡(jiǎn)單易懂,容易實(shí)現(xiàn),但其缺點(diǎn)也十分明顯,即屬性和方法的共享會(huì)導(dǎo)致對(duì)原型對(duì)象的修改影響所有子類實(shí)例。
二、借用構(gòu)造函數(shù)繼承
借用構(gòu)造函數(shù)繼承是另一種比較常見(jiàn)的繼承方法,它不是通過(guò)原型鏈繼承,而是通過(guò)在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)繼承。
我們同樣以Person為父類構(gòu)造函數(shù)為例:
<script> function Person(name, age) { this.name = name; this.age = age; this.sayHello = function() { console.log("Hello, my name is " + this.name + ", and I'm " + this.age + " years old."); } } </script>
那么我們就可以創(chuàng)建一個(gè)Student子類,并在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù),如下所示:
<script> function Student(name, age, grade) { Person.call(this, name, age); this.grade = grade; } </script>
這樣我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例將只會(huì)繼承父類的屬性和方法,而不會(huì)影響到父類對(duì)象:
<script> var s = new Student("Tom", 18, "Grade 12"); s.sayHello(); // 輸出 "Hello, my name is Tom, and I'm 18 years old." console.log(s); // 輸出 {name: "Tom", age: 18, sayHello: ?, grade: "Grade 12"} </script>
借用構(gòu)造函數(shù)繼承的優(yōu)點(diǎn)是可以避免原型鏈繼承中屬性和方法的共享問(wèn)題,但它的缺點(diǎn)也很明顯,即無(wú)法復(fù)用父類的方法。
三、組合繼承
組合繼承是將原型鏈繼承和借用構(gòu)造函數(shù)繼承兩種方法結(jié)合起來(lái)的一種繼承方式,即在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù),同時(shí)讓子類的原型指向父類的實(shí)例。
我們可以同樣的拿Person和Student來(lái)舉例說(shuō)明:
<script> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.name + ", and I'm " + this.age + " years old."); } <br> function Student(name, age, grade) { Person.call(this, name, age); this.grade = grade; } Student.prototype = new Person(); Student.prototype.constructor = Student; </script>
這樣,我們創(chuàng)建一個(gè)Student實(shí)例時(shí),該實(shí)例既能夠復(fù)用父類的方法,又能夠避免原型鏈繼承中對(duì)原型對(duì)象的修改影響所有子類實(shí)例的問(wèn)題:
<script> var s = new Student("Tom", 18, "Grade 12"); s.sayHello(); // 輸出 "Hello, my name is Tom, and I'm 18 years old." console.log(s); // 輸出 {name: "Tom", age: 18, grade: "Grade 12"} </script>
組合繼承的優(yōu)點(diǎn)是既能夠復(fù)用父類的方法,又能夠避免原型鏈繼承中的問(wèn)題,但它的缺點(diǎn)也十分明顯,即會(huì)調(diào)用兩次父類構(gòu)造函數(shù),一次在繼承prototype的時(shí)候,一次在調(diào)用父類的構(gòu)造函數(shù)時(shí)。
四、原型式繼承
原型式繼承是ES5之前最常用的一種繼承方式,它借助Object.create方法來(lái)實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的繼承,即讓一個(gè)對(duì)象作為另一個(gè)對(duì)象的原型,從而達(dá)到繼承的效果。
我們可以用一個(gè)例子來(lái)解釋原型式繼承:
<script> var person = { name: "Tom", greeting: function() { console.log("Hello, my name is " + this.name); } } <br> var s = Object.create(person); s.name = "Jerry"; s.greeting(); // 輸出 "Hello, my name is Jerry" </script>
從上面的例子中可以看出,Object.create方法是一個(gè)非常省事的繼承方式,只要傳遞一個(gè)對(duì)象作為參數(shù)就可以創(chuàng)建出一個(gè)新的對(duì)象,新對(duì)象從原對(duì)象中繼承其屬性和方法。但它的缺點(diǎn)也同樣明顯,即無(wú)法解決引用類型的問(wèn)題。
綜合4種繼承方法的優(yōu)缺點(diǎn),我們可以看出,每種繼承方式都有其適用的場(chǎng)景和注意事項(xiàng)。選擇合適的繼承方式能夠有效地提高代碼的復(fù)用性和可維護(hù)性,避免在代碼實(shí)現(xiàn)中出現(xiàn)另一個(gè)繼承過(guò)程的問(wèn)題。
下一篇div 嵌套表格