聊一聊Javasript繼承

??前前后后已經快寫了2年左右javaScript,剛開始只是簡單用于一些表單驗證和操作dom節點,并沒有深入的使用,隨著漸漸的深入,開始不想去寫重復的代碼(懶的開始),從而寫簡單的繼承,封裝,抽象等等,最終效果寫重復代碼少、可用性高(主要:迭代快、代碼可以持續使用,加班也少)

Demo構造函數聲明類

function Person(name){
    this.name = name;
}
new生成實例

new生成實例的缺點:無法共享屬性和方法,每次new新的實例會開辟新的內存空間,造成極大的資源浪費。

var personA = new Person('小明');
console.log(personA.name);

構造函數的this指向新的實例
如:

function Person(name){
    this.name = name;
    this.sex = '女'
}

var personA = new Person('小明');
var personB = new Person('小妞');
personA.sex = '男';
console.log(personB.sex);  //女

在這里我們該采用聲明解決方案呢?設計者很好的解決了這個問題,那么就是prototype屬性(包含對象)的引入

prototype屬性

它的好處是,實例一旦創建,將自動共同持有共享屬性和方法,如:

function Person(name){
    this.name = name;
}
Person.prototype.sex = '女';
var personA = new Person('小明');
var personB = new Person('小妞');
console.log(personA.sex);  //女
console.log(personB.sex);  //女

//證明它們是共享的
Person.prototype.sex = '男';
console.log(personA.sex);  //男
console.log(personB.sex);  //男

也許在這里你看不出prototype的好處,但是當你有很多方法和屬性時,你的運行效率還高嘛?那么:

function Person(name, sex){
    this.name = name;
    this.sex = sex,
    this.country = '中國',
    this.show = function(){
        console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
    }
}
var personA = new Person('小明'.'男');
personA.show();   //小明的國籍是是中國,性別:男
var personB = new Person('小妞','女');
personB.show();  //小妞的國籍是是中國,性別:女

感覺似乎沒有什么問題,但是personA和personB都包含有country、show屬性方法一模一樣的內容,這樣就造成了空間的浪費,效率也降低了,那么我們可以它們共享屬性和方法

function Person(name, sex){
    this.name = name;
    this.sex = sex,
}

Person.prototype.country = '中國';
Person.prototype.show = function(){
    console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
}

var personA = new Person('小明'.'男');
var personB = new Person('小妞','女');
personA.show();   //小明的國籍是是中國,性別:男
personB.show();  //小妞的國籍是是中國,性別:女

配合protorype使用的屬性--isPrototypeOf(),hasOwnPrototype(),in

function Person(name, sex){
    this.name = name;
    this.sex = sex,
}

Person.prototype.country = '中國';
Person.prototype.show = function(){
    console.log(this.name + '的國籍是:'+this.country+',性別:'+this.sex);
}

//isPrototypeOf() 判斷實例和對象之間的關系
console.log(Person.prototype.isPrototype(personA))  //true
console.log(Person.prototype.isPrototype(personB))  //true

//hasOwnPrototype() 判斷屬性是本地屬性,還是繼承自prototype屬性
console.log(personA.hasOwnPrototy('name'))  //true
console.log(personA.hasOwnPrototy('country'))  //false

//in 判斷是否含有屬性,不管本地還是繼承prototype
console.log('name' in personA)  //true
console.log('country' in personA)  //true

constructor屬性

繼續使用前面Person原型對象

function Person(name){
    this.name = name;
}
Person.prototype.sex = '女';
var personA = new Person('小明');
var personB = new Person('小妞');
//新增的實例自動包含有constructor屬性
console.log(personA.constructor == Person);  //true
console.log(personB.constructor == Person);  //true

這里也可以使用instanceof判斷實例和原型對象之間的關系

console.log(personA instanceof Person);  //true
console.log(personB instanceof Person);  //true

常用Object之間“繼承”(構造函數繼承)(5種)

假設現在有Person和Teacher兩個Object,想讓Teacher繼承Person

//Person對象
function Person(name){
    this.name = name;
}

//Teacher對象
function Teacher(age,sex){
    this.age = age;
    this.sex = sex;
}
1、:利用構造函數綁定(call或者apply)
function Teacher(age,sex,name){
    Person.apply(this,name);//Person.call(this,name);
    this.age = age;
    this.sex =sex;
}
2、:使用prototype,也就是我們前面說prototype屬性,修改constructor指向
Teacher.prototype = new Person('xiaoming'); //修改prototy對象原先的值
Teacher.prototype.constructor = Teacher;
var teacher1 = new Teacher(19,'女');
3、:直接繼承prototype
function Person(){}
person.prototype.name = "xiaoming";

function Teacher(age,sex){
    this.age = age;
    this.sex = sex;
}

//Teacher的prototype對象直接指向Person的prototype對象
Teacher.prototype = Person.prototype;
Teacher.prototype.constructor = Teacher
var teacher1 = new Teacher(19,"女");
4、中介new function(){}空對象
var Fn = new function(){};
Fn.prototype = Person.prototype;
Teacher.prototype = new Fn();
Teacher.prototype.constructor = Teacher;

//擴展封裝
function Extend(ChildObj,ParentObj){
    var Fn = new function(){};
    Fn.prototype = ParentObj.prototype;
    ChildObj.prototype = new Fn();
    ChildObj.prototype.constructor = ChildObj;
    ChildObj.uber = ParentObj.prototype;  //直接指向父對象prototype屬性
}

//Teacher繼承Person
Extend(Teacher,Person);
var teacher1 = new Teacher(19,'女');
5、拷貝繼承(完全)
function Extend(ChildObj, ParentObj) {
    var p = ParentObj.prototype;
    var c = ChildObj.prototype;
    for (var i in p) { 
        c[i] = p[i];
  }
  c.uber = p;
} 
//Teacher繼承Person
Extend(Teacher,Person);
var teacher1 = new Teacher(19,'女');

非構造函數“繼承”(3種)

//原始
var Person = {
    name: '小明'
}
var Teacher ={
    age:19,
    sex:'女'
}

這里我們如何可以讓Teacher繼承Person

1、:object方法
function object(obj){
    function Fn(){}
    Fn.prototype = obj;
    return new Fn();
}
var teacher1 = object(Person);
teacher1.age = 19;
teacher1.sex = '女';
2、:淺拷貝方法
function extendCopy(ParentObj){
    var c = {};
    for(var i in ParentObj){
        c[i] = p[i];
    }
    c.uber = p;
    return c;
}
//使用extendCopy
var teacher1 =  extendCopy(Person);
teacher1.age = 19;
teacher1.sex = '女';
3、:深拷貝方法
function extendDeepCopy(ParentObj,ChildObj){
    var ChildObj = ChildObj || {};
    for(var i in ParentObj){
        if(typeof  ParentObj[i] === 'object'){
            c[i] = (ParentObj[i].constructor === Array) ? [] : {};
            extendDeepCopy(ChildObj[i],ParentObj[i]);
        }else{
            ChildObj[i] = ParentObj[i];
        }
    }
    return ChildObj;
}

//使用
var teacher1 = extendDeepCopy(Person1);
teacher1.age = 19;
teacher1.sex = '女';

本文版權歸作者共有,歡迎轉載,須保留此段聲明,并給出原文鏈接,謝謝!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容