JS面向?qū)ο?--原型與繼承

正文

  • 每一個函數(shù)都有一個prototype屬性洪橘,它是一個指針指向?qū)ο蠹找В@個對象就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的的對象實例的原型對象。

Person.prototype == man

  • 所有的原型對象(Person.prototype)里面有一個屬性(constructor)指向prototype屬性所在的函數(shù)指針芝此,即構(gòu)造函數(shù)(Person)搀暑。

Person.prototype.constructor == Person

  • 構(gòu)造函數(shù)創(chuàng)建的實例對象(man),默認(rèn)會包含一個內(nèi)部屬性(_proto_)哟忍,指向構(gòu)造函數(shù)的原型對象(Person.prototype)

man._proto_ == Person.prototype

原型的語法:

function Person(){}
Person.prototype.name = 'NIKE';
Person.prototype.size = 29;
var man = new Person();

也可以用對象字面量來重寫:

function Person(){}
Person.prototype = {
  constructor : Person,
  name : 'NIKE',
  size : 29
}

注意:重寫原型對象的時候梅屉,該原型對象的constructor指向的不再是它對象的構(gòu)造函數(shù)筐带,而是object的構(gòu)造函數(shù),所以必須在重寫中顯示定義constructor為Person

通過原型可以給原生的引用類型增加方法:

String.prototype.test = function(){}
var str = 'sssssss';
str.test();

原型模式的缺點:原型中所有的屬性都是共享的寂呛,所有實例對象都會共享

解決辦法:構(gòu)造函數(shù)+原型對象

function Person(name,size){
  this.name = name;
  this.size = size;
}
Person.prototype.say = function(){
  return this.name;
}

另外兩種構(gòu)造模式:

  1. 寄生構(gòu)造模式:(類似于工廠模式)
function Person(name,size){
  var o = new object();
  o.name = name;
  o.size = size;
  o.say = function(){
    return this.name;
  }
  return o;
}
  1. 穩(wěn)妥構(gòu)造模式:(沒有公共屬性)
function Person(name,size){
  var o = new object();
  o.say = function(){
    return name;
  }
}

這兩種模式的問題是:創(chuàng)建的對象跟構(gòu)造函數(shù)沒有一毛錢關(guān)系怎诫。

繼承

1.原型鏈繼承
function Super(){}
Super.prototype.say = function(){
  return 1;
}
function Sub(){}
Sub.prototype = new Super();
//覆蓋
Sub.prototype.say = function(){
  return 2;
}

原理:創(chuàng)建Super的實例,然后把該實例賦給Sub.prototype贷痪,那么Sub.prototype則擁有Sup的所有屬性和方法幻妓,當(dāng)通過Sub構(gòu)造函數(shù)實例一個對象后,該對象不僅包含Sub的屬性和對象劫拢,同時還包含Sup的肉津,即實現(xiàn)了繼承

注意:通過原型鏈實現(xiàn)繼承的時候,不能使用對象字面量舱沧,會重寫原型鏈妹沙。

缺點:原型屬性會被所有實例共享,并且不能想超類行的構(gòu)造函數(shù)(Super)傳遞參數(shù)熟吏。

2. 借用構(gòu)造函數(shù)
function Super(name){
  this.name = name;
}
function Sub(name){
  Super.call(this,name)
}

優(yōu)點:可以傳遞參數(shù)
缺點:方法都在構(gòu)造函數(shù)里面定義距糖,沒有函數(shù)復(fù)用的意義

3.組合繼承
function Super(name){
  this.name = name;
}
Super.prototype.say = function(){
  return this.name;
}
function Sub(name,age){
  //繼承屬性
  Super.call(this,name);
  this.age = age;
}
//繼承方法
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;

缺點:需要調(diào)用兩次構(gòu)造函數(shù)(call和實例化)

4.原型式繼承
var person = {
  name : 'NIKE',
  age : 29
}
var anotherPerson = Object.create(person);

優(yōu)點:不需要創(chuàng)建構(gòu)造函數(shù)
缺點:跟原型模式一樣,會共享屬性

題外:Object.create的實現(xiàn):

function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}
5.寄生組合式繼承(最理想的繼承方式)
function inheritPrototype(sub,sup){
  var prototype = Object.create(sup.prototype);
  prototype.constructor = sub;
  sub.prototype = prototype;
}
function Super(name){
  this.name = name;
}
Super.prototype.say = function(){
  return this.name;
}
function Sub(name,age){
  Super.call(this,name);
  this.age = age;
}
inheritPrototype(Sub,Super);

優(yōu)點:不必為了子類型的原型而調(diào)用超類型的構(gòu)造函數(shù)(我們所需要的無非是超類型原型的一個副本)

面向?qū)ο笾袪砍兜降姆椒ǎ?/h4>
  1. Object.defineProperty() 定義對象數(shù)據(jù)的屬性
var person = {}
Object.defineProperty(person,"name",{
  writable : false, //只讀
  configurable : false, //不可配置牵寺,一旦設(shè)置為false,不可再進(jìn)行配置
  enumerable : false, //不可枚舉悍引,不能通過for..in循環(huán)
  value : 'NIKE'
})

定義多個屬性 Object.defineProperties

Object.defineProperties(person,{
  name : 'NIke',
  _year:{  //_命名規(guī)則,表示該屬性屬于私有屬性
    writable : true,
    value : 2004
  },
  year:{
    get:function(){
      return this._year;
    },
    set:function(value){
      this._year = value;
    }
  }
});
  1. A instanceof B 判斷A是否是B的實例
man instanceof Person == true
man instanceof Object == true
  1. Object.getPrototypeOf() 返回實例對象的內(nèi)部屬性(_proto_)
Object.getPrototypeOf(man) == Person.prototype
  1. A.prototype.isPrototypeOf(B) 判斷A.prototype是否是B的原型對象
Person.prototype.isPrototypeOf(man)
  1. A.hasOwnProperty(B) 檢測一個屬性B是存在于實例A中(true)帽氓,還是存在于原型中(false)
man.hasOwnProperty('name')
  1. hasPrototypeProperty(A,B) 與方法5正好相反趣斤,只不過使用方法略有不同
  2. Object.keys(A) 返回對象A中所有可枚舉屬性,以字符串?dāng)?shù)組返回

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末黎休,一起剝皮案震驚了整個濱河市唬渗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奋渔,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壮啊,死亡現(xiàn)場離奇詭異嫉鲸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)歹啼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門玄渗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狸眼,你說我怎么就攤上這事藤树。” “怎么了拓萌?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵岁钓,是天一觀的道長。 經(jīng)常有香客問我,道長屡限,這世上最難降的妖魔是什么品嚣? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮钧大,結(jié)果婚禮上翰撑,老公的妹妹穿的比我還像新娘。我一直安慰自己啊央,他們只是感情好眶诈,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瓜饥,像睡著了一般逝撬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上压固,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天球拦,我揣著相機(jī)與錄音,去河邊找鬼帐我。 笑死坎炼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拦键。 我是一名探鬼主播谣光,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芬为!你這毒婦竟也來了萄金?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤媚朦,失蹤者是張志新(化名)和其女友劉穎氧敢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體询张,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡孙乖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了份氧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唯袄。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜗帜,靈堂內(nèi)的尸體忽然破棺而出恋拷,到底是詐尸還是另有隱情,我是刑警寧澤厅缺,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布蔬顾,位于F島的核電站宴偿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏阎抒。R本人自食惡果不足惜酪我,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望且叁。 院中可真熱鬧都哭,春花似錦、人聲如沸逞带。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽展氓。三九已至穆趴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遇汞,已是汗流浹背未妹。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留空入,地道東北人络它。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像歪赢,于是被迫代替她去往敵國和親化戳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容