js對象學(xué)習(xí)筆記

對象字面量

 var person = {
    name:"aa",
    age:20,
    job:"student",
    sayName:function(){
        alert(this.name);
    }
}

工廠模式

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("aa",20,"student");
var person2 = createPerson("bb",22,"teacher");

構(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("aa",20,"student");
var person2 = new Person("bb",22,"teacher");

構(gòu)造函數(shù)始終應(yīng)以大寫字母開頭徽曲,非構(gòu)造函數(shù)則以小寫字母開頭。
要?jiǎng)?chuàng)建Person的新實(shí)例,必須用new操作符朋譬。

person1和person2都有一個(gè)constructor(構(gòu)造函數(shù))屬性,該屬性指向Person兴垦。

person1.constructor == Person; //true

優(yōu)于工廠模式:可以將他的實(shí)例表示為一種特定的類型而非只是Object徙赢。

 person1 instanceof Person //true

構(gòu)造函數(shù)與其它函數(shù)的區(qū)別在于調(diào)用方式不同。任何函數(shù)通過new操作符調(diào)用都會(huì)作為構(gòu)造函數(shù)探越,反之不通過new操作符調(diào)用那么就是普通函數(shù)狡赐。

//當(dāng)做構(gòu)造函數(shù)
var person1 = new Person("aa",20,"student");
person1.sayName(); //aa

//作為普通函數(shù)
Person("ee",20,"student");//添加到window
window.sayName();//ee

//在另一個(gè)對象的作用域中調(diào)用
var o = new Object();
Person.call(o,"cc",34,"mother");
o.sayName(); //cc

作為普通函數(shù)調(diào)用時(shí),在全局作用域中調(diào)用的函數(shù)this指向window對象钦幔。

構(gòu)造函數(shù)缺點(diǎn):每個(gè)方法都會(huì)在每個(gè)實(shí)例上重新創(chuàng)造一遍枕屉。不同實(shí)例上的同名函數(shù)是不相等的。

原型模式

原型對象:包含所有實(shí)例共享的屬性和方法鲤氢。

function Person(){
}
Person.prototype.name = "aa";
Person.prototype.age = 20;
Person.prototype.job = "student";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
person1.sayName(); //"aa"

var person2 = new Person();
person2.sayName(); //"aa"

person1.sayName == person2.sayName; //true

上例中所有實(shí)例訪問同一組屬性與方法搀擂。

原型對象.jpg

檢測是否是實(shí)例的原型對象:

Person.prototype.isPrototypeOf(person1); //true

Object.getPrototypeOf(person1) == Person.prototype; //true

Object.getPrototypeOf方便地取得一個(gè)對象的原型西潘。

搜索屬性:
當(dāng)代碼讀取某個(gè)對象的某個(gè)屬性時(shí),都會(huì)執(zhí)行一次搜索哨颂。


原型屬性搜索.jpg

對象實(shí)例可以訪問原型中的值喷市,但不能重寫。若實(shí)例中添加了一個(gè)與原型中某一個(gè)屬性同名的屬性威恼,則該屬性會(huì)屏蔽原型中的同名屬性:

function Person(){
}
Person.prototype.name = "aa";
Person.prototype.age = 20;
Person.prototype.job = "student";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
person1.sayName(); //"aa"

var person2 = new Person();
person2.sayName(); //"aa"

person1.name = "bb" ;
person1.name; //"bb"---來自實(shí)例
person2.name; //"aa"---來自原型

使用delete操作符可以刪除實(shí)例屬性:

person1.name = "bb" ;
person1.name; //"bb"---來自實(shí)例
person2.name; //"aa"---來自原型

delete person1.name;
person1.name; //"aa" ---來自原型

hasOwnProperty:檢測一個(gè)屬性存在于實(shí)例還是存在于原型品姓。

person1.hasOwnProperty("name"); //false

person1.name = "bb" ;
person1.name; //"bb"---來自實(shí)例
person1.hasOwnProperty("name"); //true

delete person1.name;
person1.name; //"aa" ---來自原型
person1.hasOwnProperty("name"); //false

單獨(dú)使用in操作符:對象能訪問給定屬性時(shí)返回true,無論此屬性是來自實(shí)例還是原型箫措。

function Person(){
}
Person.prototype.name = "aa";
Person.prototype.age = 20;
Person.prototype.job = "student";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
var person2 = new Person();

person1.hasOwnProperty("name"); //false
"name" in person1 //true

person1.name = "bb" ;
person1.name; //"bb"---來自實(shí)例
person1.hasOwnProperty("name"); //true
"name" in person1 //true

因此利用hasOwnProperty與in可以判斷一個(gè)屬性是來自實(shí)例還是原型腹备。

function hasPrototypeProperty(object,name){
    return !object.hasOwnPeoperty(name)&&(name in object);
}

使用for-in時(shí),返回的是對象能訪問的蒂破,可枚舉的屬性馏谨,其中包括來自實(shí)例的也包括來自原型的。

Object.keys( )方法可返回對象上所有可枚舉的實(shí)例屬性:

function Person(){
}
Person.prototype.name = "aa";
Person.prototype.age = 20;
Person.prototype.job = "student";
Person.prototype.sayName = function(){
    alert(this.name);
};
var keys = Object.keys(Person.prototype); //["name", "age", "job", "sayName"]

var person1 = new Person();
var keys = Object.keys(person1 );//[]

person1.name = "bb";
person1.age = 23;
var keys = Object.keys(person1 );//["name", "age"]

獲取所有實(shí)例屬性而無論其是否可枚舉:Object.getOwnPropertyNames( )

var keys = Object.getOwnPropertyNames(Person.prototype);//["constructor", "name", "age", "job", "sayName"]

結(jié)果中包含了不可枚舉的constructor屬性附迷。
Object.keys與Object.getOwnPropertyNames均可替代for-in惧互。

更簡單的原型語法

function Person(){
}
Person.prototype = {
    name:"aa",
    age:20,
    job:"student",
    sayName:function(){
        alert(this.name);
    }
}

但是在這種語法下,本質(zhì)上是完全重寫了默認(rèn)的prototype對象喇伯,因此constructor屬性也就不再指向Person而是Object喊儡。
若constructor屬性十分重要,則可以像下面這樣:

function Person(){
}
Person.prototype = {
    constructor:Person,
    name:"aa",
    age:20,
    job:"student",
    sayName:function(){
        alert(this.name);
    }
}

而此時(shí)由用戶重設(shè)的constructor屬性已經(jīng)變成了可枚舉的了稻据。

由于在原型中查找值的過程是一次搜索艾猜,因此對原型對象所做的任何修改都能夠立即從實(shí)例上反映出來,即使是先創(chuàng)建實(shí)例后修改原型捻悯。

function Person(){}
var friend = new Person();
Person.prototype.sayHi =function(){
    alert("Hi");
}
friend.sayHi(); //Hi

由于實(shí)例和原型間是松散連接關(guān)系匆赃,其間不過是一個(gè)指針,因此通過上面的搜索屬性就可以在原型中找到新的方法今缚。

但是如果重寫整個(gè)原型對象的話(如上面的更簡單的原型語法)算柳,由于調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)指向最初原型的指針,如果把原型指向另一個(gè)對象就等于切斷了新原型與已經(jīng)存在的實(shí)例之間聯(lián)系姓言,也切斷了構(gòu)造函數(shù)與舊原型的聯(lián)系瞬项。已經(jīng)存在的實(shí)例引用的仍是最初的原型。

function Person(){}
var friend = new Person();
Person.prototype = {
    constructor:Person,
    name:"aa",
    age:20,
    job:"student",
    sayName:function(){
        alert(this.name);
    }
}
friend.sayName(); //error

下圖展示了上列過程:

重寫原型對象.jpg

原生對象如Object何荚,Array囱淋,String等都是在其構(gòu)造函數(shù)的原型上定義了方法。我們也可以用此方法定義新方法:

String.prototype.startWith = function(text){
    return this.indexOf(text)==0;
}
var msg = "hello world";
alert(msg.startWith("hello")); //true

原型對象也有缺點(diǎn):
1.省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié)餐塘,結(jié)果所有實(shí)例在默認(rèn)情況下都會(huì)取得相同的屬性值妥衣。
2.原型中的屬性是被多實(shí)例共享的,對于基本值屬性還好,因?yàn)榭梢酝貙懗屏郏珜τ诎妙愋椭档膶傩詠碚f涮较,就會(huì)有如下問題:

function Person(){
}
Person.prototype = {
    constructor:Person,
    name:"aa",
    age:20,
    job:"student",
    friends:["bb","cc"],
    sayName:function(){
        alert(this.name);
    }
}
var person1 = new Person();
var person2 = new Person();

person1.friends.push("dd");

person1.friends;//"bb,cc,dd"
person2.friends;//"bb,cc,dd"
person1.friends == person2.friends; //true

組合使用構(gòu)造函數(shù)模式與原型模式

創(chuàng)建自定義類型的最常見方式,構(gòu)造函數(shù)用于定義實(shí)例屬性冈止,原型用于定義方法和共享的屬性狂票。結(jié)果,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性同時(shí)又共享者對方法的引用熙暴,最大限度地節(jié)省了內(nèi)存闺属。

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["bb","cc"];
}

Person.prototype = {
    constructor:Person,
     sayName:function(){
        alert(this.name);
    }
}

var person1 = new Person("alice",30,"students");
var person2 = new Person("bob",34,"ceo");

person1.friends.push("dd");
person1.friends;//"bb,cc,dd"
person2.friends;//"bb,cc"

person1.friends == person2.friends; //false
person1.sayName == person2.sayName; //true

動(dòng)態(tài)原型模式

把所有信息都封裝在構(gòu)造函數(shù)中,通過在構(gòu)造函數(shù)中初始化原型周霉,同時(shí)保證了構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)掂器。

function Person(name,age,job){
    //屬性
    this.name = name;
    this.age = age;
    this.job = job;
  
    //方法
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name);
        };
    }
}

var friend = new Person("alice",30,"students");
friend.sayName(); //alice

if檢測那段代碼只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)執(zhí)行,此后原型已經(jīng)完成初始化俱箱,之后調(diào)用構(gòu)造函數(shù)創(chuàng)建的實(shí)例都會(huì)有sayname屬性国瓮,不會(huì)走if里面的語句。if語句檢查的可以是初始化之后應(yīng)該存在的屬性或方法狞谱。

使用動(dòng)態(tài)函數(shù)模型時(shí)不能使用對象字面量重寫原型乃摹,否則會(huì)切斷現(xiàn)有實(shí)例與新原型之間的聯(lián)系。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末跟衅,一起剝皮案震驚了整個(gè)濱河市孵睬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伶跷,老刑警劉巖掰读,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叭莫,居然都是意外死亡蹈集,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門雇初,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雾狈,“玉大人,你說我怎么就攤上這事抵皱。” “怎么了辩蛋?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵呻畸,是天一觀的道長。 經(jīng)常有香客問我悼院,道長伤为,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮绞愚,結(jié)果婚禮上叙甸,老公的妹妹穿的比我還像新娘。我一直安慰自己位衩,他們只是感情好裆蒸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糖驴,像睡著了一般僚祷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贮缕,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天辙谜,我揣著相機(jī)與錄音,去河邊找鬼感昼。 笑死装哆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的定嗓。 我是一名探鬼主播蜕琴,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蜕乡!你這毒婦竟也來了奸绷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤层玲,失蹤者是張志新(化名)和其女友劉穎号醉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辛块,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畔派,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了润绵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片线椰。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尘盼,靈堂內(nèi)的尸體忽然破棺而出憨愉,到底是詐尸還是另有隱情,我是刑警寧澤卿捎,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布配紫,位于F島的核電站,受9級特大地震影響午阵,放射性物質(zhì)發(fā)生泄漏躺孝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望植袍。 院中可真熱鬧惧眠,春花似錦、人聲如沸于个。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽览濒。三九已至呆盖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贷笛,已是汗流浹背应又。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乏苦,地道東北人株扛。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像汇荐,于是被迫代替她去往敵國和親洞就。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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