JavaScript高級程序設(shè)計讀書筆記 第六章 OO

JS中對象的定義:無序?qū)傩缘募现锌瘢鋵傩灾悼梢园局担瑢ο蠡蛘吆瘮?shù)扑毡。我們可以把js的對象想象成散列表胃榕,無非就是一組鍵值對,其中的值可以是數(shù)據(jù)或函數(shù)瞄摊。
屬性有兩種類型:數(shù)據(jù)屬性和訪問器屬性勋又。
數(shù)據(jù)屬性:包含一個數(shù)據(jù)值的位置,在這個位置可以讀取和寫入值换帜。數(shù)據(jù)屬性有四個特性:

  • configurable 屬性能否delete掉楔壤,屬性特性能否修改,能否把數(shù)據(jù)屬性變?yōu)樵L問器屬性

  • enumerable 能否通過for in循環(huán)返回屬性

  • writable 能否修改屬性的值

  • value 屬性的數(shù)據(jù)值

    var person = {};
      //person的name屬性值為Jack 不可修改值
      Object.defineProperty(person,"name",{
          writable:false,
          value:"Jack"
      });
      alert(person.name);
      person.name="Grey";
      alert(person.name);
      Object.defineProperty(person,"age",{
          configurable:false,
          value:22
      })
      alert(person.age);
      delete person.age;//configurable為false惯驼,不能修改
      alert(person.age);
    

訪問器屬性:不包含數(shù)據(jù)值蹲嚣,它們包含一對getter和setter函數(shù)递瑰。

  • configurable 屬性能否delete掉,屬性特性能否修改隙畜,能否把數(shù)據(jù)屬性變?yōu)樵L問器屬性

  • enumerable 能否通過for in循環(huán)返回屬性

  • get 讀取屬性時調(diào)用的函數(shù)

  • set 寫入屬性時調(diào)用的函數(shù)
    訪問器屬性不能直接定義抖部,需通過defineProperty來定義。在調(diào)用該方法時议惰,如果不指定慎颗,configurable,enumerable换淆,writable特性的默認值都是false

    var book={
        _year:2004,
        edition:1
      };
      Object.defineProperty(book,"year",{
          get:function(){
              return this._year;
          },
          set:function(newValue){
              if(newValue>2004){
                  this._year=newValue;
                  this.edition+=newValue-2004;
              }
          }
      });
      book.year=2006;
      alert(book.edition);
      book._year=2007;//直接設(shè)置下劃線屬性的值也會起作用
    

_year前面的下劃線是一種常用的記號哗总,用于表示只能通過對象方法定義的屬性。_year是數(shù)據(jù)屬性倍试,year是訪問器屬性
定義多個屬性 通過描述符一次定義多個屬性讯屈,第一個參數(shù)是要修改的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應(yīng)

    var book={};
    Object.defineProperties(book,{
        _year:{
            value:2004
        },
        edition:{
            value:1
        },
        year:{
            get:function(){
                return this._year;
            },
            set:function(){
                if(arguments[0]>2004){
                    this._year=arguments[0];
                    this.edition+=arguments[0]-2004;
                }
            }
        }

    })
  var des=Object.getOwnPropertyDescriptor(book,"_year");
    console.log(des);//讀取屬性描述符

6.2 創(chuàng)建對象
工廠模式

  function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o.sayname=function(){
        alert(this.name);
    };
    return o;
  }
  var person1=createPerson("jack",22,"worker");
  person1.sayname();
  console.log(person1);
  alert(person1 instanceof Object);//工廠模式的壞處县习,無法確定對象類型涮母,都是Object

構(gòu)造函數(shù)模式

  function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayname=function(){
        alert(this.name);
    }
  }
  var person1 = new Person("jack",33,"workers")
  person1.sayname();
  console.log(person1);
  alert(person1 instanceof Person);//構(gòu)造函數(shù)可以確定對象類型 但是實例上每個方法都要在實例上創(chuàng)建一遍

原型模式
我們創(chuàng)建的每個函數(shù)都有一個prototype屬性,這個屬性是一個指針躁愿,指向一個對象叛本,這個對象包含特定類型的所有實例共享的屬性和方法。

  function Person(){

  }
  Person.prototype.name="jack";
  Person.prototype.age=29;
  Person.prototype.job="coder";
  Person.prototype.sayname=function(){
    alert(this.name);
  }
  var person1 = new Person();
  person1.sayname();//jack
  var person2 = new Person();
  person2.name="lucy";
  person2.sayname();//lucy
  person1.sayname();//jack

三者關(guān)系

無論什么時候彤钟,只要創(chuàng)建一個新函數(shù)来候,就會為該函數(shù)創(chuàng)建一個prototype屬性,這個屬性指向函數(shù)的原型對象逸雹。而原型對象里也有一個constructor指針指向該函數(shù)营搅。當用函數(shù)創(chuàng)建一個新實例以后,這個實例的內(nèi)部的proto指針將指向原型梆砸。

console.log(Object.getPrototypeOf(person1));//實例對應(yīng)的原型

每當讀取某個對象的某個屬性時转质,搜索首先從對象實例本身開始,如果找到了則返回對應(yīng)的值帖世,找不到到原型對象里找休蟹。
我們在實例對象里添加一個屬性,即使和原型里的某個屬性重名日矫,也不會覆蓋原型里的屬性赂弓。

person1.city="beijing";
alert(person1.hasOwnProperty('city'));//屬性在實例中返回true true
alert(person1.hasOwnProperty('name'));//false

in 只要屬性能找到就返回true

alert("job" in person1);
for(var p in person1){//遍歷所有屬性,包括原型中的
    alert(p);
}
alert(Object.keys(person1));//返回所有屬性組成的字符串哪轿,不包含原型

字面量重寫原型對象

function Person(){}
//字面量重寫原型對象
Person.prototype={
    constructor:Person//重寫設(shè)定指針
    name:"jack",
    age:29,
    job:"coder",
    sayName:function(){
        alert(this.name);
    }
}

原型中查找值的過程是一次搜索拣展,因此我們對原型對象所做的任何修改都能立即從實例上反應(yīng)出來,即使先創(chuàng)建實例后修改原型也照樣如此缔逛。
原型模式的缺點:如果屬性是引用類型备埃,一個實例的修改會導(dǎo)致所有實例的值都被修改姓惑。
創(chuàng)建自定義類型的最常見方式是組合使用構(gòu)造函數(shù)模式和原型模式。(實例屬性用構(gòu)造按脚,方法和共享屬性用原型)

function Person(name,age,job){
    this.name=name;
   this.age=age;
    this.job=job;
    this.friends=["lucy","bob"];
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}
var person1=new Person("jack",22,"worker");

繼承

主要依靠原型鏈來完成
讓某個實例的原型對象等于另一類型的實例于毙。

function Person(name,age,job){
    this.name=name;
   this.age=age;
    this.job=job;
    this.friends=["lucy","bob"];
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}
function Student(school){
    this.school=school;
}
Student.prototype=new Person();
Student.prototype.saySchhol=function(){
    alert(this.school);
};
var s1=new Student("ustc");
s1.name="jack";
s1.age=12;
s1.sayName();
console.log(s1);

原型鏈的問題:一 父類的引用屬性,子類一但修改辅搬,所有子類實例的值都會變化唯沮,二 無法向父類傳遞構(gòu)造參數(shù)。

借用構(gòu)造函數(shù)

在子類的構(gòu)造函數(shù)內(nèi)部調(diào)用父類構(gòu)造函數(shù)

function Student(school){
    Person.call(this);//每個子類都會有父類屬性的拷貝副本
    this.school=school;
}

組合繼承
使用原型鏈實現(xiàn)對原型屬性和方法的繼續(xù)堪遂,而借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承介蛉。

function  Person(name){
     this.name=name;
 }
 Person.prototype.sayname=function(){
     alert(this.name);
 }
function Student(name,school,score){
    Person.call(this,name);
    this.school=school;
    this.score=score;
}
Student.prototype=new Person("Jack");
Student.saySChool=function(){
    alert(this.school);
}
var s1=new Student("lucy","ustc",99);
var s2=new Student("mike","autc",80);
console.log(s1);
console.log(s2);
s1.sayname();
s2.sayname();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市溶褪,隨后出現(xiàn)的幾起案子币旧,更是在濱河造成了極大的恐慌,老刑警劉巖猿妈,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吹菱,死亡現(xiàn)場離奇詭異,居然都是意外死亡彭则,警方通過查閱死者的電腦和手機鳍刷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俯抖,“玉大人输瓜,你說我怎么就攤上這事》移迹” “怎么了前痘?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長担忧。 經(jīng)常有香客問我,道長坯癣,這世上最難降的妖魔是什么瓶盛? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮示罗,結(jié)果婚禮上惩猫,老公的妹妹穿的比我還像新娘。我一直安慰自己蚜点,他們只是感情好轧房,可當我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绍绘,像睡著了一般奶镶。 火紅的嫁衣襯著肌膚如雪迟赃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天厂镇,我揣著相機與錄音纤壁,去河邊找鬼。 笑死捺信,一個胖子當著我的面吹牛酌媒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迄靠,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼秒咨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了掌挚?” 一聲冷哼從身側(cè)響起雨席,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疫诽,沒想到半個月后舅世,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡奇徒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年雏亚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摩钙。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡罢低,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胖笛,到底是詐尸還是另有隱情网持,我是刑警寧澤,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布长踊,位于F島的核電站功舀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏身弊。R本人自食惡果不足惜辟汰,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阱佛。 院中可真熱鬧帖汞,春花似錦、人聲如沸凑术。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淮逊。三九已至催首,卻和暖如春扶踊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翅帜。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工姻檀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涝滴。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓绣版,卻偏偏與公主長得像,于是被迫代替她去往敵國和親歼疮。 傳聞我的和親對象是個殘疾皇子杂抽,可洞房花燭夜當晚...
    茶點故事閱讀 43,687評論 2 351

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