js中的對(duì)象揭鳞,構(gòu)造函數(shù),原型梆奈,原型鏈野崇,繼承

對(duì)象

創(chuàng)建對(duì)象

  • 方式1-字面量表示,推薦使用
var a = {};
  • 方式2-調(diào)用構(gòu)造函數(shù),不推薦使用
var obj = new Object();
//Object是所有對(duì)象的基礎(chǔ)
  • 方式3 亩钟,自定義方法,形式和函數(shù)一樣乓梨,為了區(qū)分,構(gòu)造函數(shù)命名嚴(yán)格按照大駝峰形式(所有單詞首字母大寫(xiě))
function Person(){}
var person = new Person();

Object的所有實(shí)例都有下列屬性和方法,因此所有的對(duì)象都有這些屬性和方法

  • constructor
  • hasOwnProperty(propertyName)
    --->propertyName必須為字符串類(lèi)型
  • propertyIsEnunerable(propertyName)
    --->propertyName必須為字符串類(lèi)型
  • isPrototypeOf(object)
  • toString()
  • valueOf()
  • toLocaleString()

使用構(gòu)造函數(shù)創(chuàng)建對(duì)象模式

    function Person(name,age,job){
        this.name=name;
        this.age=age;
        this.job=job;
        this.sayName=function(){
            console.log(this.name);
        };
    }
    var person1 = new Person('xiaoli',29,'doctor');
    var person1 = new Person('xiaozhang',38,'teacher');
    console.log(person1.constructor ==Person);//true
    console.log(person2.constructor ==Person);//true

構(gòu)造函數(shù)原理

構(gòu)造函數(shù)和普通函數(shù)的唯一區(qū)別就是名字要首字母大寫(xiě)和要用new實(shí)例化
要?jiǎng)?chuàng)建Person的實(shí)例清酥,必須使用new扶镀,以這種方式調(diào)用構(gòu)造函數(shù)實(shí)際上會(huì)經(jīng)歷4個(gè)階段

  • 創(chuàng)建一個(gè)新對(duì)象
  • 新對(duì)象名字叫this(構(gòu)造函數(shù)的作用域賦予新對(duì)象)
  • 執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性)this.xxx=xxx;
  • 返回新對(duì)象 return this
構(gòu)造函數(shù)的注意點(diǎn)
  • 不同實(shí)例的同名函數(shù)是不相等的。
  • 所以創(chuàng)建兩個(gè)完成同樣任務(wù)的Function實(shí)例沒(méi)有必要,況且由this對(duì)象在焰轻,根本不用再執(zhí)行代碼前就把函數(shù)綁定在特定對(duì)象上
  • 把函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部來(lái)解決這個(gè)問(wèn)題
    function Person(name,age,job){
        this.name=name;
        this.age=age;
        this.job=job;
        this.sayName=sayName;
    }
    function sayName(){
            console.log(this.name);
        }
    var person1 = new Person('xiaoli',29,'doctor');
    var person1 = new Person('xiaozhang',38,'teacher');
但是這樣又有新的問(wèn)題臭觉。
  • 在全局作用域中定義的sayName只能被某個(gè)函數(shù)調(diào)用,
  • 如果需要定義很多方法辱志,那就要定義很多全局函數(shù)蝠筑,沒(méi)有封裝性
  • 通過(guò)原型模式來(lái)解決

原型模式

我們創(chuàng)建的每一個(gè)函數(shù)都有prototype屬性,prototype也是對(duì)象揩懒,是構(gòu)造函數(shù)制造出來(lái)的對(duì)象的公共祖先什乙,創(chuàng)造出來(lái)的原型可以繼承原型里面的屬性和方法

  • JavaScript 的所有對(duì)象中都包含了一個(gè) __proto__ 內(nèi)部屬性,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型
  • JavaScript 的函數(shù)對(duì)象已球,除了原型 __proto__ 之外臣镣,還預(yù)置了 prototype 屬性
  • 當(dāng)函數(shù)對(duì)象作為構(gòu)造函數(shù)創(chuàng)建實(shí)例時(shí)辅愿,該 prototype 屬性值將被作為實(shí)例對(duì)象的原型 __proto__

  • prototype是通過(guò)調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對(duì)象實(shí)例退疫,的原型對(duì)象

不必再構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息渠缕,而是將信息直接添加到原型對(duì)象中

function Person(){}
Person.prototype.name="lia";
Person.prototype.age=19;
Person.prototype.sayName=function(){
    console.log(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.sayName();
person2.sayName();
理解原型對(duì)象
  • 無(wú)論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù)褒繁,就會(huì)為該函數(shù)創(chuàng)建一個(gè)prototype屬性。這個(gè)屬性指向函數(shù)的原型對(duì)象
  • 在默認(rèn)情況下馍忽,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性棒坏,這個(gè)屬性是一個(gè)指向prototype屬性所在函數(shù)的指針,

Person.prototype.constructor指向Person

  • 創(chuàng)建一個(gè)自定義的構(gòu)造函數(shù)后遭笋,其原型對(duì)象只會(huì)默認(rèn)取得constructor屬性坝冕,至于其他方法,都是從Object繼承來(lái)的
  • 構(gòu)造函數(shù)初始化時(shí)瓦呼,新建的this空對(duì)象其實(shí)不是空的喂窟,里面自帶一條__proto__:Person.prototype,用來(lái)指引實(shí)例函數(shù)尋找他的原型
  • 在調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例后,該實(shí)例的內(nèi)部將包含一個(gè)指針央串,指向該構(gòu)造函數(shù)的原型對(duì)象磨澡。es5管這個(gè)指針叫[[prototype]]
  • 腳本中沒(méi)有標(biāo)準(zhǔn)的方法訪問(wèn)[[prototype]],但Firefox,safari和chrome在每個(gè)對(duì)象上都支持一個(gè)屬性proto,而在其他實(shí)現(xiàn)中质和,這個(gè)屬性對(duì)腳本則是完全不可見(jiàn)的稳摄。
  • 這個(gè)鏈接存在于 實(shí)例函數(shù) 和 構(gòu)造函數(shù)的原型對(duì)象 之間,而不是存在于實(shí)例和構(gòu)造函數(shù)之間
  • 函數(shù)才有prototype饲宿,實(shí)例對(duì)象只有有proto厦酬, 而函數(shù)有的proto是因?yàn)楹瘮?shù)是Function的實(shí)例對(duì)象
以以上 Person構(gòu)造函數(shù)為例
  • Person.prototype指向了原型對(duì)象,而Person.prototype.cunstructor又指向了Person,

其他注意點(diǎn)

  • 當(dāng)為對(duì)象實(shí)例添加一個(gè)屬性是瘫想,這個(gè)屬性會(huì) <em>屏蔽</em> 原型對(duì)象中保存的同名屬性仗阅。(添加這個(gè)同名屬性只會(huì)阻止我們?cè)L問(wèn)原型對(duì)象中的那個(gè)屬性,而不會(huì)修改那個(gè)屬性国夜。)减噪。即使這個(gè)屬性為null
  • 但是,使用delete操作符可以完全刪除實(shí)例屬性支竹,從而可以可以重新訪問(wèn)原型中的屬性

原型鏈-使用proto連接

任意一個(gè)函數(shù)(包括構(gòu)造函數(shù))都有一個(gè)prototype屬性旋廷,指向該函數(shù)的原型對(duì)象,同樣任意一個(gè)構(gòu)造函數(shù)實(shí)例化的對(duì)象礼搁,都有一個(gè)proto屬性

Grande.prototype.lastname="你爺爺";
function Grande(){}
var grande = new Grande();

Father.prototype=grande;
function Father (){}
var father = new Father();

Son.prototype=father;
function Son (){}
var son = new Son();
console.log(son.lastname);//你爺爺

Grande.prototype.proto--->Object.prototype

  • 絕大多數(shù)對(duì)象的最終饶碘,都會(huì)繼承自O(shè)bject.protype

var obj = Object.create(null)
這樣就沒(méi)有原型了,因?yàn)閚ull和undefined沒(méi)有toString方法

  • 重寫(xiě)toString方法
            Number.prototype.toString=function(){
                return "你要返回的東西";
            }

方法

isPrototypeOf()

console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true
//因?yàn)镻erson1和Person2內(nèi)部都有一個(gè)指向Person的指針馒吴,所以返回true

Object.getPrototypeOf

返回這個(gè)對(duì)象的原型

hasOwnPrototype()

一個(gè)屬性是存在實(shí)例中扎运,而不是存在于原型對(duì)象中瑟曲,返回ture,繼承自O(shè)bject
使用for-in循環(huán)是豪治,會(huì)循環(huán)實(shí)例和原型對(duì)象里面的屬性洞拨,

確認(rèn)屬性是原型中的屬性

function hasPrototypeProperty(object,name){
    return (name in object) && !object.hasOwnPrototype(name);
}
//左邊的卡確認(rèn)是實(shí)例或者原型的屬性,左邊返回ture后负拟,右邊的如果是原型里面的屬性烦衣,則整體返回true

proto和prototype的聯(lián)系和區(qū)別

function a() {
    //console.log("I'am a function.");
}
//b是實(shí)例化對(duì)象,a是構(gòu)造函數(shù)
 var b = new a();
 console.log(b.__proto__ == a.prototype); //true
 //一個(gè)對(duì)象的隱式原型指向構(gòu)造該對(duì)象的構(gòu)造函數(shù)的原型掩浙,這也保證了實(shí)例能夠訪問(wèn)在構(gòu)造函數(shù)原型中定義的屬性和方法花吟。
console.log(Object.getPrototypeOf(b) == a.prototype); //true


區(qū)別:

  • 區(qū)別:prototype是構(gòu)造函數(shù)訪問(wèn)原型對(duì)象,proto是對(duì)象實(shí)例訪問(wèn)原型對(duì)象厨姚。
  • proto是每個(gè)對(duì)象都有的一個(gè)屬性衅澈,而prototype是函數(shù)才會(huì)有的屬性!!!
  • 使用Object.getPrototypeOf()代替proto

注意: 函數(shù)才有prototype,實(shí)例對(duì)象只有有proto谬墙, 而函數(shù)有的proto是因?yàn)楹瘮?shù)是Function的實(shí)例對(duì)象

繼承

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

在構(gòu)造函數(shù)中 使用Parent.call(this)的方法繼承父類(lèi)屬性今布。

原理: 將子類(lèi)的this使用父類(lèi)的構(gòu)造函數(shù)跑一遍

缺點(diǎn): Parent原型鏈上的屬性和方法并不會(huì)被子類(lèi)繼承

function Parent() {
  this.name = 'parent'
}

function Child() {
  Parent.call(this);
  this.type = 'child'
}

原型鏈實(shí)現(xiàn)繼承

原理:把子類(lèi)的prototype(原型對(duì)象)直接設(shè)置為父類(lèi)的實(shí)例

Son.prototype=new Father();

缺點(diǎn):當(dāng)子類(lèi)對(duì)象上進(jìn)行值修改時(shí),如果是修改的原始類(lèi)型的值拭抬,那么會(huì)在實(shí)例上新建這樣一個(gè)值部默;
但如果是引用類(lèi)型的話,他就會(huì)去修改子類(lèi)上唯一一個(gè)父類(lèi)實(shí)例里面的這個(gè)引用類(lèi)型玖喘,這會(huì)影響所有子類(lèi)實(shí)例

繼承圣杯模式

* 繼承圣杯模式

var inherit =(function(){
    var F = function(){};//利用閉包甩牺,實(shí)現(xiàn)變量私有化
    return function(Target,Origin){
        F.prototype = Origin.prototype;
        Target.prototype= new F();
        //通過(guò)原型鏈連接
        Targer.prototype.constructor = Target;
        Target.prototype.uber = Origin.prototype;
    }
}());

對(duì)象的遍歷

for in

var obj= {
    name:123,
    age:33,
    __proto__:{
        lastName:deng;
    }
}
for(bar i in obj){
    //為了不訪問(wèn)到原型里面的方法
    if(obj.hasOwnProperty(i)){
        console,log(i+":"+obj[i]);
    }
}
//i是一個(gè)字符串累奈,如果寫(xiě)成obj.i,系統(tǒng)會(huì)轉(zhuǎn)換成obj['i']贬派,就成屬性讀取,澎媒,所以必須要寫(xiě)方括號(hào)搞乏,
//如果是系統(tǒng)自帶的原型,沒(méi)程序員設(shè)置戒努,他就不會(huì)打印出來(lái)请敦,。要程序員自己設(shè)置的原型储玫,才會(huì)被打印出來(lái)

object.name與object["name"]

  • 使用方括號(hào)讀取對(duì)象屬性(替代點(diǎn)方式)-比較靈活
var obj = {
    name:"xiaoli"
}
obj.name;//用這種方式訪問(wèn)侍筛,會(huì)在后臺(tái)轉(zhuǎn)換成方括號(hào)模式
obj['name'];
//這兩種方式,本質(zhì)來(lái)說(shuō)是一樣的撒穷,方括號(hào)比較靈活
  • 應(yīng)用
 var deng = {
     wife1:{name:"1111"},
     wife2:{name:"22222"},
     wife3:{name:"3333"},
     wife4:{name:"4444"},
     sayWife:function(num){
         console.log(deng['wife'+num]);
     }  
 }

模擬Jquery實(shí)現(xiàn)鏈?zhǔn)骄幊?/h4>
var deng = {
    smoke : function(){
       console.log("smoking...");
       return this
    },
    sayHi:function(){
        console.log("hello");
        return this;
    }
}
deng.smoke().sayHi();

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匣椰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子端礼,更是在濱河造成了極大的恐慌禽笑,老刑警劉巖入录,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異佳镜,居然都是意外死亡僚稿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)蟀伸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蚀同,“玉大人,你說(shuō)我怎么就攤上這事啊掏』秸福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵脖律,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我腕侄,道長(zhǎng)小泉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任冕杠,我火速辦了婚禮微姊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘分预。我一直安慰自己兢交,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布笼痹。 她就那樣靜靜地躺著配喳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凳干。 梳的紋絲不亂的頭發(fā)上晴裹,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音救赐,去河邊找鬼涧团。 笑死,一個(gè)胖子當(dāng)著我的面吹牛经磅,可吹牛的內(nèi)容都是我干的泌绣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼预厌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼阿迈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起配乓,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仿滔,失蹤者是張志新(化名)和其女友劉穎惠毁,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體崎页,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞠绰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了飒焦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜈膨。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牺荠,靈堂內(nèi)的尸體忽然破棺而出翁巍,到底是詐尸還是另有隱情,我是刑警寧澤休雌,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布灶壶,位于F島的核電站,受9級(jí)特大地震影響杈曲,放射性物質(zhì)發(fā)生泄漏驰凛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一担扑、第九天 我趴在偏房一處隱蔽的房頂上張望恰响。 院中可真熱鬧,春花似錦涌献、人聲如沸胚宦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)枢劝。三九已至,卻和暖如春利术,著一層夾襖步出監(jiān)牢的瞬間呈野,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工印叁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留被冒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓轮蜕,卻偏偏與公主長(zhǎng)得像昨悼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跃洛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • ??面向?qū)ο螅∣bject-Oriented汇竭,OO)的語(yǔ)言有一個(gè)標(biāo)志葱蝗,那就是它們都有類(lèi)的概念穴张,而通過(guò)類(lèi)可以創(chuàng)建任意...
    霜天曉閱讀 2,098評(píng)論 0 6
  • 普通創(chuàng)建對(duì)象和字面量創(chuàng)建對(duì)象不足之處:雖然 Object 構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢杂脕?lái)創(chuàng)建單個(gè)對(duì)象,但這些方式有...
    believedream閱讀 2,362評(píng)論 2 18
  • 什么是原型語(yǔ)言 只有對(duì)象,沒(méi)有類(lèi);對(duì)象繼承對(duì)象,而不是類(lèi)繼承類(lèi)两曼。 “原型對(duì)象”是核心概念皂甘。原型對(duì)象是新對(duì)象的模板,...
    zhoulujun閱讀 2,320評(píng)論 0 12
  • JS中原型鏈悼凑,說(shuō)簡(jiǎn)單也簡(jiǎn)單偿枕。 首先明確: 函數(shù)(Function)才有prototype屬性,對(duì)象(除Object...
    前小白閱讀 3,911評(píng)論 0 9
  • 每一天都在經(jīng)歷著各種形式的別離户辫,與人渐夸,與事,甚至與這可愛(ài)的天氣渔欢。 讀過(guò)許多別離的詩(shī)墓塌,看過(guò)很多別離的信,卻依...
    吃魚(yú)的姨閱讀 367評(píng)論 0 3