『壹』 js實現繼承的幾種方法
《繼承法》第二十三條 繼承開始後,知道被繼承人死亡的繼承人應當及時通知其他繼承人和遺囑執行人。繼承人中無人知道被繼承人死亡或者知道被繼承人死亡而不能通知的,由被繼承人生前所在單位或者住所地的居民委員會、村民委員會負責通知。第二十四條 存有遺產的人,應當妥善保管遺產,任何人不得侵吞或者爭搶。第二十五條 繼承開始後,繼承人放棄繼承的,應當在遺產處理前,作出放棄繼承的表示。沒有表示的,視為接受繼承。受遺贈人應當在知道受遺贈後兩個月內,作出接受或者放棄受遺贈的表示,到期沒有表示的,視為放棄受遺贈。第二十六條 夫妻在婚姻關系存續期間所得的共同所有的財產,除有約定的以外,如果分割遺產,應當先將共同所有的財產的一半分出為配偶所有,其餘的為被繼承人的遺產。遺產在家庭共有財產之中的,遺產分割時,應當先分出他人的財產。第二十七條 有下列情形之一的,遺產中的有關部分按照法定繼承辦理:遺囑繼承人放棄繼承或者受遺贈人放棄受遺贈的;遺囑繼承人喪失繼承權的;遺囑繼承人、受遺贈人先於遺囑人死亡的;遺囑無效部分所涉及的遺產;遺囑未處分的遺產。第二十八條 遺產分割時,應當保留胎兒的繼承份額。胎兒出生時是死體的,保留的份額按照法定繼承辦理。第二十九條 遺產分割應當有利於生產和生活需要,不損害遺產的效用。不宜分割的遺產,可以採取折價、適當補償或者共有等方法處理。第三十條 夫妻一方死亡後另一方再婚的,有權處分所繼承的財產,任何人不得干涉。第三十一條 公民可以與扶養人簽訂遺贈扶養協議。按照協議,扶養人承擔該公民生養死葬的義務,享有受遺贈的權利。公民可以與集體所有制組織簽訂遺贈扶養協議。按照協議,集體所有制組織承擔該公民生養死葬的義務,享有受遺贈的權利。第三十二條無人繼承又無人受遺贈的遺產,歸國家所有;死者生前是集體所有制組織成員的,歸所在集體所有制組織所有。第三十三條 繼承遺產應當清償被繼承人依法應當繳納的稅款和債務,繳納稅款和清償債務以他的遺產實際價值為限。超過遺產實際價值部分,繼承人自願償還的不在此限。繼承人放棄繼承的,對被繼承人依法應當繳納的稅款和債務可以不負償還責任。第三十四條 執行遺贈不得妨礙清償遺贈人依法應當繳納的稅款和債務。
『貳』 Web前端學習之Javascript繼承的常用4種方法
今天小編要跟大家分享的文章是關於Javascript繼承的常用4種方法。相信很多學習web前端開發技術的小夥伴在學習前端開發的javascript部分的時候,在面向對象的部分就很難走下去了,主要的原因還是邏輯更加復雜了,需要理解的內容比直觀的開發布局難一點。
在面向對象編程里,封裝和繼承是比較重要的,這中間,薯鏈手繼承是相對而言比較難理解的,因為javascript的繼承方式比較多,也有不同的優缺點。今天小編為大家帶來這篇文章就是來和大家一起說一說Javascript繼承的常用4種方法,希望能夠對你有所幫助。
1、原型鏈繼承
核心:將父類的實例作為子類的原型
缺點:父類新增原型方法/原型屬性,子類都能訪問到,父類一變其它的都變了
2、構造繼承
基本思想
借用構造函數的基本思想就是利用call或者apply把父類中通過this指定的屬性和方法復制(借用)到子類創建的實例中。
因為this對象是在運行時基於函數的執行環境綁定的。也就是說,在全局中,this等於window,而當函數被作為某個對象的方法調用時,this等於那個對象。
call、apply方法可將一個函數的對象上下文從初始的上下文改變為由thisObj指定的新對象。
所以,這個借用構造函數就是,new對象的時候(new創建的時候,this指喚昌向創建的這個實例),創建了一個新的實例對象,並且執行Parent裡面的代碼,而Parent裡面用call調用了Person,也就是說把this指向改成了指向新的實例,所以就會把Person裡面的this相關屬性和方法賦值到新的實例上,而不是賦值到Person上面,所以所有實例中就擁有了父類定義的這些this的屬性和方法。
因為屬性是綁定到this上面的,所以調用的時候才賦到相應的實例中,各個實例的值就不會互相影響了。
核心:使用父類的構造函數來增強子類實例,等於是復制父類的實例屬性給子類(沒用到原型)
缺點:方法都在構造函數中定義,
只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法,無法實現函數復用,每個子類都有父類實例函數的數嫌副本,影響性能
3、組合繼承
組合繼承(所有的實例都能擁有自己的屬性,並且可以使用相同的方法,組合繼承避免了原型鏈和借用構造函數的缺陷,結合了兩個的優點,是最常用的繼承方式)
核心:通過調用父類構造,繼承父類的屬性並保留傳參的優點,然後再通過將父類實例作為子類原型,實現函數復用
缺點:調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
4、寄生組合繼承
核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
缺點:堪稱完美,但實現較為復雜
以上就是小編今天為大家分享的關於web前端學習之Javascript繼承的常用4種方法的文章,希望本篇文章能夠對正在學習web前端技術的小夥伴們有所幫助。想要了解更多web前端知識記得關注北大青鳥web培訓官網。
文章轉載自公眾號:前端研究所
『叄』 javascript實現繼承有哪些方式
Javascript的繼承在很多書裡面細致的分了很多種類型和實現方式,大體上就是兩種:對象冒充、原型方式。這兩種方式各有優點和缺陷,這里我給你先列舉出來,再從底層分析區別:
(一)對象冒充
function A(name){
this.name = name;
this.sayHello = function(){alert(this.name+」 say Hello!」);};
}
function B(name,id){
this.temp = A;
this.temp(name); //相當於new A();
delete this.temp; //防止在以後通過temp引用覆蓋超類A的屬性和方法
this.id = id;
this.checkId = function(ID){alert(this.id==ID)};
}
當構造對象B的時候,調用temp相當於啟動A的構造函數,注意這里的上下文環境中的this對象是B的實例,所以在執行A構造函數腳本時,所有A的變數 和方法都會賦值給this所指的對象,即B的實例,這樣子就達到B繼承了A的屬性方法的目的。之後刪除臨時引用temp,是防止維護B中對A的類對象(注 意不是實例對象)的引用更改,因為更改temp會直接導致類A(注意不是類A的對象)結構的變化。
我們看到了,在Js版本更新的過程中,為了更方便的執行這種上下文this的切換以達到繼承或者更加廣義的目的,增加了call和apply函數。它們的 原理是一樣的,只是參數不同的版本罷了(一個可變任意參數,一個必須傳入數組作為參數集合)。這里就以call為例子,解釋一下用call實現的對象冒充 繼承。
function Rect(width, height){
this.width = width;
this.height = height;
this.area = function(){return this.width*this.height;};
}
function myRect(width, height, name){
Rect .call(this,width,height);
this.name = name;
this.show = function(){
alert(this.name+」 with area:」+this.area());
}
}
關於Call方法,官方解釋:調用一個對象的一個方法,以另一個對象替換當前對象。
call (thisOb,arg1, arg2…)
這也是一種對象冒充的繼承,其實在call方法調用的時候發生的事情也是上下文環境變數this的替換,在myRect函數體中this肯定是指向類 myRect對象的實例了,然而用這個this作為上下文環境變數調用名字叫Rect方法,即類Rect的構造函數。於是此時調用Rect時候對this 的賦值屬性和方法都實際上是對一個myRect的對象進行。所以說盡管call和apply並不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。
對象冒充繼承就是這么一回事,它可以實現多重繼承,只要重復做這一套賦值的流程就可以了。不過目前真正大規模使用得並不多,為什麼呢?因為它有一個明顯的 性能缺陷,這就要說道OO的概念了,我們說對象是成員+成員方法的集合,構造對象實例的時候,這些實例只需要擁有各自的成員變數就可以了,成員方法只是一 段對變數操作的可執行文本區域而已,這段區域不用為每個實例而復制一份,所有的實例都可以共享。現在回到Js利用對象冒充模擬的繼承里,所有的成員方法都 是針對this而創建的,也就是所所有的實例都會擁有一份成員方法的副本,這是對內存資源的一種極度浪費。其它的缺陷比如說對象冒充無法繼承 prototype域的變數和方法就不用提了,筆者認為前一個致命缺陷就已經足夠。不過,我們還是需要理解它,特別是父類的屬性和方法是如何繼承下來的原 理,對於理解Js繼承很重要。
(二)原型方式
第二種繼承方式是原型方式,所謂原型方式的繼承,是指利用了prototype或者說以某種方式覆蓋了prototype,從而達到屬性方法復制的目的。 其實現方式有很多中,可能不同框架多少會有一點區別,但是我們把握住原理,就不會有任何不理解的地方了。看一個例子(某一種實現):
function Person(){
this.name = 「Mike」;
this.sayGoodbye = function(){alert(「GoodBye!」);};
}
Person.prototype.sayHello = function(){alert(」Hello!」);};
function Student(){}
Student.prototype = new Person();
關鍵是對最後一句Student原型屬性賦值為Person類構造的對象,這里筆者解釋一下父類的屬性和方法是如何到子類上的。Js對象在讀取某 個對象屬性的時候,總是先查看自身域的屬性列表,如果有就返回否則去讀取prototype域(每個對象共享構造對象的類的prototype域所有屬性 和方法),如果找到就返回,由於prototype可以指向別的對象,所以Js解釋器會遞歸的去查找prototype域指向對象的prototype 域,直到prototype為本身,查找變成了一種循環,就停止,此時還沒找到就成undefined了。
這樣看來,最後一句發生的效果就是將父類所有屬性和方法連接到子類的prototype域上,這樣子類就繼承了父類所有的屬性和方法,包括name、 sayGoodbye和sayHello。這里與其把最後一句看成一種賦值,不如理解成一種指向關系更好一點。這種原型繼承的缺陷也相當明顯,就是繼承時 父類的構造函數時不能帶參數,因為對子類prototype域的修改是在聲明子類對象之後才能進行,用子類構造函數的參數去初始化父類屬性是無法實現的, 如下所示:
function Person(name){
this.name = name;
}
function Student(name,id){
this.id = id;
}
Student.prototype = new Person(this.name);
兩種繼承方式已經講完了,如果我們理解了兩種方式下子類如何把父類的屬性和方法「抓取」下來,就可以自由組合各自的利弊,來實現真正合理的Js繼承。下面是個人總結的一種綜合方式:
function Person(name){
this.name = name;
}
Person.prototype.sayHello = function(){alert(this.name+「say Hello!」);};
function Student(name,id){
Person.call(this,name);
this.id = id;
}
Student.prototype = new Person();
Student.prototype.show = function(){
alert(「Name is:」+ this.name+」 and Id is:」+this.id);
}
總結就是利用對象冒充機制的call方法把父類的屬性給抓取下來,而成員方法盡量寫進被所有對象實例共享的prototype域中,以防止方法副本重復創 建。然後子類繼承父類prototype域來抓取下來所有的方法。如想徹底理清這些調用鏈的關系,推薦大家多關注Js中prototype的 constructor和對象的constructor屬性,這里就不多說了。
『肆』 js繼承的幾種方式 各
js繼承用的還是比較少的,一般通過原型鏈繼承或混合繼承目的就是降低創建對象的開銷!
各種繼承示例如下:
<script>
//把父類方法放到其原型鏈中而非類聲明體中,以便每次實例化子類時不至於都執行函數而增加創建對象的開銷
Person.prototype.speakP=function(){
console.log("I'maPerson!");
};
functionPerson(age,name){
this.age=age;
this.name=name;
}
functionStudent(sno,age,name){
Person.call(this,age,name);
this.sno=sno;
}
vars=newStudent(95001,23,"小紅");
console.log(Student.prototype.constructor);
//s.speakP();//s不是Person類型,所以不能調用speakP函數;如果非要調用,可使用以下方案二:原型鏈繼承
</script>
<script>
Person.prototype.speakP=function(){
console.log("I'maPerson!age="+this.age+"name="+this.name);//通過實例化的子類對象調用我時獲取不到父類的age、name
};
functionPerson(age,name){
this.age=age;
this.name=name;
}
Student.prototype=newPerson();
//因為修改了Student原型鏈,需要把其原型鏈上構造器重新指向自己
Student.prototype.constructor=Student;
functionStudent(sno,age,name){
this.sno=sno;
}
vars=newStudent(95001,23,"小紅");
console.log(Student.prototype.constructor);
s.speakP();
</script>
<script>
Person.prototype.speakP=function(){
console.log("I'maPerson!age="+this.age+"name="+this.name);
};
functionPerson(age,name){
this.age=age;
this.name=name;
}
Student.prototype=newPerson();
Student.prototype.constructor=Student;
functionStudent(sno,age,name){
Person.call(this,age,name);
this.sno=sno;
}
vars=newStudent(95001,23,"小紅");
console.log(Student.prototype.constructor);
s.speakP();
</script>
<script>
classPerson{
constructor(age,name){
this.age=age;
this.name=name;
}
sayHi(){
console.log("I'maPerson!age="+this.age+"name="+this.name);
}
}
classStudentextendsPerson{
constructor(sno,age,name){
super(age,name);
this.sno=sno;
}
}
vars=newStudent(95001,24,"小紅");
console.log(Student.prototype.constructor);
s.sayHi();
</script>
『伍』 關於JS實現繼承的方法都有哪一些
定義一個父類:
// 定義一個動物類
function Animal (name) {
// 屬性
this.name = name || 『Animal』;
// 實例方法
this.sleep = function(){
console.log(this.name + 『正在睡覺!』);
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + 『正在吃:』 + food);
1.原型鏈繼承
核心:將父類的實例作為子類的原型
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 『cat』;
//Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat(『fish』));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
特點:
1.非常純粹的繼承關系,實例是子類的實例,也是父類的實例
2.父類新增的原型方法、屬性,子類都能訪問到
3.簡單,易於實現
缺點:
1.要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之後執行
(可以在cat構造函數中,為Cat實例增加實例屬性)
2.無法實現多繼承
3.來自原型對象的引用屬性被所有實例共享
4.創建子類實例時,無法向父類構造函數傳參
下面代碼解釋缺點3(注意是引用屬性):
function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2
2.構造繼承
核心:使用父類的構建函數來增強子類實例,等於復制父類的實例屬性給子類(沒用到原型),除了call方法,也可以用apply()
function Cat(name){
Animal.call(this);
this.name = name || 『Tom』;
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特點:
1.解決了1中,子類實例共享父類引用屬性的問題
2.創建子類實例時,可以向父類傳遞參數
3.可以實現多繼承(call多個父類對象)
缺點:
1.實例並不是父類的實例,只是子類的實例
2.只能繼承父類的實例屬性和方法,不能繼承原型屬性和方法
3.無法實現函數復用,每個子類都有父類的實例函數的副本,影響性能
3.實例繼承
核心:為父類實例添加新特性,作為子類實例返回
function Cat(name){
var instance = new Animal();
instance.name = name || 『Tom』;
return instance;
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
特點:
1.不限制調用方式,不管是new 子類()還是子類(),返回的對象都具有相同的效果
缺點:
1.實例是父類的實例,不是子類的實例
2.不支持多繼承
4. 拷貝繼承
核心:使用for…in將父類實例中的方法賦給子類實例
unction Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || 『Tom』;
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特點:
1.支持多繼承
缺點:
1.效率較低,內存佔用高(因為要拷貝父類的屬性)
2.無法獲取父類不可枚舉的方法(for in無法訪問不可枚舉的方法)
5.組合繼承
核心:通過調用父類構造,繼承父類的屬性並保留傳參的優點,然後通過將父類實例作為子類原型,實現函數復用
function Cat(name){
Animal.call(this);
this.name = name || 『Tom』;
}
Cat.prototype = new Animal();
//組合繼承需要修復構造函數的指向
Cat.prototype.constructor=Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
特點:
1.彌補了方式2的缺陷,可以繼承實例屬性、方法,也可以繼承原型屬性、方法
2.既是子類的實例,也是父類的實例
3.不存在引用屬性的共享問題
4.可傳參
5.函數可復用
缺點:
1.調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
6.寄生組合繼承
核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
function Cat(name){
Animal.call(this);
this.name = name || 『Tom』;
}
(function(){
// 創建一個沒有實例方法的類
var Super = function(){};
Super.prototype = Animal.prototype;
//將實例作為子類的原型
Cat.prototype = new Super();
//寄生組合繼承需要修復構造函數的指向
Cat.prototype.constructor=Cat;
})();
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
特點:
1.堪稱完美
缺點:
1.實現較為復雜 (BY三人行慕課)