成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

js中的面向?qū)ο笕腴T(mén)

sihai / 557人閱讀

摘要:簡(jiǎn)單來(lái)理解對(duì)象就是由屬性和方法來(lái)組成的面向?qū)ο蟮奶攸c(diǎn)封裝對(duì)于一些功能相同或者相似的代碼,我們可以放到一個(gè)函數(shù)中去,多次用到此功能時(shí),我們只需要調(diào)用即可,無(wú)需多次重寫(xiě)。

什么是對(duì)象

我們先來(lái)看高程三中是如何對(duì)對(duì)象進(jìn)行定義的

"無(wú)序?qū)傩缘募?,其屬性可以包括基本值、?duì)象或者函數(shù)",對(duì)象是一組沒(méi)有特定順序的的值。對(duì)象的沒(méi)個(gè)屬性或方法都有一個(gè)俄名字,每個(gè)名字都映射到一個(gè)值。

簡(jiǎn)單來(lái)理解對(duì)象就是由屬性和方法來(lái)組成的

面向?qū)ο蟮奶攸c(diǎn)

-封裝

對(duì)于一些功能相同或者相似的代碼,我們可以放到一個(gè)函數(shù)中去,多次用到此功能時(shí),我們只需要調(diào)用即可,無(wú)需多次重寫(xiě)。

在這里我們可以理解為創(chuàng)造對(duì)象的幾種模式:?jiǎn)卫J剑S模式,構(gòu)造函數(shù)模式,原型模式等。

繼承

子類(lèi)可以繼承父類(lèi)的屬性和方法

多態(tài)(重載和重寫(xiě))

重載:嚴(yán)格意義上說(shuō)js中沒(méi)有重載的功能,不過(guò)我們可以通過(guò)判斷函數(shù)的參數(shù)的不同來(lái)實(shí)現(xiàn)不同的功能來(lái)模擬重載。

重寫(xiě):子類(lèi)可以改寫(xiě)父類(lèi)的屬性和方法

javascript中的封裝

單例模式
小王在一個(gè)小公司,就自己一個(gè)前端,所以他寫(xiě)js都是這樣的

var a = 1;
function getNum(){
    return 1;
}

后來(lái)公司又招了個(gè)前端小明,于是變成他們2個(gè)一起寫(xiě)同一個(gè)js了。一天小王發(fā)現(xiàn)自己寫(xiě)的getNum方法出問(wèn)題了,原來(lái)是小華寫(xiě)的js中也有個(gè)getNum的函數(shù),代碼合并后把他的覆蓋掉了,于是便找小華理論去,經(jīng)過(guò)一番妥協(xié)后,兩人都把自己的代碼改了改

var xiaoming = {
    num:1,
    getNum:function(){
        return 1;
    }
}

var xiaohua = {
    num:2,
    getNum: function(){
        return 2;
    }
}

這就是我們所謂的單例模式(命名空間)

我們把描述同一個(gè)事物的方法或者屬性放到同一個(gè)對(duì)象里,不同事物之間的方法或者屬性名相同相互也不會(huì)發(fā)生沖突。

單例模式的優(yōu)劣

使用單例模式,我們可以實(shí)現(xiàn)簡(jiǎn)單的模塊化開(kāi)發(fā)

var utils = {
    getCss:function(){
        //code
    },
    getByClass:function(){
         //code
    },
    setCss:function(){
        //code
    }
}

我們可以把自己寫(xiě)好的工具方法放到一個(gè)多帶帶的js文件中,然后直接引入即可。

避免了全局變量名的沖突
需要注意的是,我們?cè)谝敫鱾€(gè)模塊的時(shí)候,需要注意引入的順序,引入順序是按照各模塊之間的相互依賴(lài)進(jìn)行前后排列的;

缺點(diǎn):

單例模式只是一定程度上避免了變量名的沖突,但并不能徹底解決此問(wèn)題,而且在不同的對(duì)象下,我們可能會(huì)有很多功能相同的代碼,最終造成大量的冗余代碼。

單例模式讓每個(gè)對(duì)象有了自己獨(dú)立的命名空間,但是并不能批量生產(chǎn)的問(wèn)題,每一個(gè)新的對(duì)象都要重新寫(xiě)一份一模一樣的代碼。

var person1 = {
    name:"小明",
    age:24,
    showName:function(){
          console.log("我的名字是:"+this.name)
    }
};
var person1 = {
    name:"小華",
    age:25,
    showName:function(){
          console.log("我的名字是:"+this.name)
    }
};

工廠模式

工廠模式其實(shí)就是把需要一個(gè)個(gè)的編寫(xiě)的對(duì)象,放在一個(gè)函數(shù)中統(tǒng)一的進(jìn)行創(chuàng)建,說(shuō)白了就是普通函數(shù)的封裝。

工廠模式總共3步驟:

1)引進(jìn)原材料 --- 創(chuàng)建一個(gè)空對(duì)象
2)加工原材料 --- 加工對(duì)象:給對(duì)象添加屬性和方法;
3)輸出產(chǎn)品 --- 返回對(duì)象:return 對(duì)象;

function CreatePerson(name,age){
        var obj={};//1.創(chuàng)建一個(gè)空對(duì)象
        //2.加工對(duì)象
        obj.name=name;
        obj.age=age;
        obj.showName=function(){
            console.log("我的名字是:"+this.name)
        };
        return obj;//3.輸出對(duì)象;
}
var person1 = CreatePerson("小明",23)
var person2 = CreatePerson("小華",23)
person1.showName(); //我的名字是:小明
person2.showName(); //我的名字是:小華

工廠模式的優(yōu)缺點(diǎn)

既然叫工廠模式,它就和我們周?chē)墓S一樣,我們只需要把原材料放進(jìn)去,就能得到我們需要的產(chǎn)品了。

工廠模式也解決了單例模式的批量生產(chǎn)的問(wèn)題,避免了單例模式中的大量冗余代碼,進(jìn)行系統(tǒng)的封裝,提高代碼的重復(fù)利用率

不過(guò)工廠模式跟我們js內(nèi)置類(lèi)的調(diào)用方法不同

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

可以創(chuàng)建一個(gè)自定義的類(lèi),并且可以new出實(shí)例

構(gòu)造函數(shù)做的就是類(lèi)和實(shí)例打交道。

    //構(gòu)造函數(shù):首字母大寫(xiě)(約定俗成);
    function CreatePerson(name,age){ //創(chuàng)建一個(gè)自定義的類(lèi)
        //構(gòu)造函數(shù)中的this,都是new出來(lái)的實(shí)例
        //構(gòu)造函數(shù)中存放的都是私有的屬性和方法;
        this.name=name;
        this.age=age;
        this.showName=function(){
             console.log("我的名字是:"+this.name)
        }
    }
   //實(shí)例1
    var person1 = new CreatePerson("小明",25)
   //實(shí)例2
    var person2 = new CreatePerson("小華",24)

這里說(shuō)一下工廠模式和構(gòu)造函數(shù)模式的區(qū)別:

1. 在調(diào)用的時(shí)候不同:
工廠模式:調(diào)用的時(shí)候,只是普通函數(shù)的調(diào)用createPerson();
構(gòu)造函數(shù)模式:new CreatePerson();
2. 在函數(shù)體內(nèi)不同:
工廠模式有三步:1)創(chuàng)建對(duì)象 2)加工對(duì)象 3)返回對(duì)象;
構(gòu)造函數(shù)模式只有1步: 只有加工對(duì)象; 因?yàn)橄到y(tǒng)默認(rèn)會(huì)為其創(chuàng)建對(duì)象和返回對(duì)象;
3. 構(gòu)造函數(shù)默認(rèn)給我們返回了一個(gè)對(duì)象,如果我們非要自己手動(dòng)返回的話(huà):
    (1)手動(dòng)返回的是字符串類(lèi)型:對(duì)以前實(shí)例上的屬性和方法沒(méi)有影響;
    (2)手動(dòng)返回的是引用數(shù)據(jù)類(lèi)型:以前實(shí)例身上的屬性和方法就被覆蓋了;實(shí)例無(wú)法調(diào)用屬性和方法;

構(gòu)造函數(shù)的方法都是私有方法,每個(gè)實(shí)例調(diào)用的都是自己私有的方法,同樣也會(huì)有許多重復(fù)的代碼。

我們可以使用原型模式來(lái)解決每個(gè)實(shí)例中都有相同方法的函數(shù)的問(wèn)題

原型模式

    function CreatePerson(name,age){ 
        this.name=name;
        this.age=age;
    }
    // 我們把公有的方法放到函數(shù)的原型鏈上
    CreatePerson.prototype.showName = function(){
             console.log("我的名字是:"+this.name)
    }  
    var person1 = new CreatePerson("小明",25) 
    var person2 = new CreatePerson("小華",24)
    person1.showName() //小明

原型模式的關(guān)鍵:

1)每個(gè)函數(shù)數(shù)據(jù)類(lèi)型(普通函數(shù),類(lèi))上,都有一個(gè)屬性,叫prototype。
2)prototype這個(gè)對(duì)象上,天生自帶一個(gè)屬性,叫constructor:指向當(dāng)前這個(gè)類(lèi);
3)每個(gè)對(duì)象數(shù)據(jù)類(lèi)型(普通對(duì)象,prototype,實(shí)例)上都有一個(gè)屬性,
   叫做__proto__:指向當(dāng)前實(shí)例所屬類(lèi)的原型;

這3句話(huà)理解了,下邊的東西就可以不用看了 //手動(dòng)滑稽

通過(guò)例子我們來(lái)看這幾句話(huà)是什么意思

 function CreatePerson(name,age){
        this.name=name;
        this.age=age
}
CreatePerson.prototype.showName=function(){
             console.log("我的名字是:"+this.name)
}
var person1 = new CreatePerson("小明",25);
console.dir(person1)

在chrome瀏覽器控制臺(tái)中顯示

從圖中可以看出,person1這個(gè)對(duì)象上有name和age兩個(gè)屬性,
person1的__proto__指向了它的構(gòu)造函數(shù)(CreatePerson)的prototype上,
而且還有一個(gè)showName的方法。 并且它們中有一條鏈關(guān)聯(lián)著: person1.__proto__ ===
CreatePerson.prototype

接著來(lái)看

function Foo(){
   this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo;  //沒(méi)有參數(shù)的話(huà)括號(hào)可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

以這個(gè)為例,
當(dāng)我們查找f1.a時(shí),因?yàn)閒1中有這個(gè)屬性,所以我們得出 f1.a=1;
當(dāng)我們查找f1.b時(shí),f1中沒(méi)有這個(gè)屬性,我們便順著f1.__proto__這條鏈去
它的構(gòu)造器的prototype上找,所以我們得出了 f1.b = 3;

接著來(lái)說(shuō),F(xiàn)oo.prototype是個(gè)對(duì)象,那么它的__proto__指向哪里呢
還記的剛剛說(shuō)的那句
每個(gè)對(duì)象數(shù)據(jù)類(lèi)型(普通對(duì)象,prototype,實(shí)例)上都有一個(gè)屬性,叫做__proto__:指向當(dāng)前實(shí)例所屬類(lèi)的原型
此外,我們應(yīng)該知道
每一個(gè)對(duì)象都是function Object這個(gè)構(gòu)造函數(shù)的實(shí)例

所以我們可以接著還原這個(gè)原型圖

等等,圖上貌似多了個(gè)個(gè)Object.prototype.__proto__ 指向了null,這是什么鬼?

我們這么來(lái)理解,Object.prototype是個(gè)對(duì)象, 那么它的__proto__指向了它的構(gòu)造函數(shù)的prototype上,
最后發(fā)現(xiàn)了還是指向它自身,這樣轉(zhuǎn)了個(gè)圈貌似是無(wú)意義的,于是便指向了null

還沒(méi)完,我們發(fā)現(xiàn)對(duì)象都是函數(shù)(構(gòu)造器)創(chuàng)造出來(lái)的,那么函數(shù)是誰(shuí)創(chuàng)造的呢?石頭里蹦出來(lái)的么?
在js中,function都是由function Function這個(gè)構(gòu)造器創(chuàng)造的,每一個(gè)函數(shù)都是Function的實(shí)例

現(xiàn)在基本上我們就能得出了完整的原型圖了

是不是有點(diǎn)亂?根據(jù)我們剛剛講的是能把這個(gè)圖理順的,
這里需要注意下,F(xiàn)unction.__proto__是指向它的prototype的

多說(shuō)一點(diǎn),判斷數(shù)據(jù)類(lèi)型的方法時(shí),我們知道有個(gè)instanceof的方法
比如

A instanceof B

instanceof判斷的規(guī)則就是:

沿著A的__proto__這條線(xiàn)查找的同時(shí)沿著B(niǎo)的prototype這條線(xiàn)來(lái)找,如果兩條線(xiàn)能找到同一個(gè)引用(對(duì)象),那么就返回true。如果找到終點(diǎn)還未重合,則返回false。

再來(lái)看我們之前的那個(gè)例子

function Foo(){
   this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo;  //沒(méi)有參數(shù)的話(huà)括號(hào)可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

當(dāng)我們查找f1.a時(shí),因?yàn)閒1中有這個(gè)屬性,所以我們得出 f1.a=1;
當(dāng)我們查找f1.b時(shí),f1中沒(méi)有這個(gè)屬性,我們便順著f1.__proto__這條鏈去它的構(gòu)造器的prototype上找,所以我們得出了 f1.b = 3;

當(dāng)我們查找一個(gè)對(duì)象的屬性時(shí),先在這個(gè)對(duì)象的私有空間內(nèi)查找,如果沒(méi)找到,就順著對(duì)象的__proto__這條鏈去它的構(gòu)造器的ptototype上查找,如果還沒(méi)找到,接著沿__proto__向上查找,直到找到Object.prototype還沒(méi)有的話(huà),這個(gè)值就為undefined,這就是所謂的原型鏈

列舉下網(wǎng)頁(yè)中的一些相關(guān)的原型鏈

有興趣的同學(xué)可自行通過(guò)瀏覽器控制臺(tái)看看我們常用的方法都是在哪個(gè)類(lèi)上定義的,比如getElementsByTagName,addEventListener等等

繼承

在這里就主要說(shuō)一下組合繼承(call + 原型鏈)

function Father(){
    this.xxx= 80;
    this.yyy= 100;
    this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
    this.aaa = 120;
    this.singing = function(){}
    Father.call(this);
}
Son.prototype = new Father;
Son.prototype.constructor = Son;
var son = new Son
console.dir(son)

這么寫(xiě)有個(gè)不好的地方就是:子類(lèi)私有的屬性中有父類(lèi)私有的屬性,子類(lèi)公有的屬性中也有父類(lèi)私有的屬性;
根據(jù)我們前邊的知識(shí),我們可以這么來(lái)改寫(xiě)

function Father(){
    this.xxx= 80;
    this.yyy= 100;
    this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
    this.aaa = 120;
    this.singing = function(){}
    Father.call(this);
}
Son.prototype.__proto__ = Father.prototype
var son = new Son
console.dir(son)

最后來(lái)一張思維導(dǎo)圖

圖片如果放大也看不清的話(huà) 下載地址

如有錯(cuò)誤,歡迎指正!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81835.html

相關(guān)文章

  • JS基礎(chǔ)入門(mén)篇(三十六)—面向對(duì)象( 三 )

    摘要:所以不會(huì)報(bào)錯(cuò)函數(shù)聲明可以先調(diào)用再聲明函數(shù)聲明解析時(shí),不會(huì)放到前面。所以會(huì)報(bào)錯(cuò)報(bào)錯(cuò)多個(gè)方法之間直接書(shū)寫(xiě)不需要隔開(kāi)我會(huì)說(shuō)話(huà)解析其中方法和方法之間并沒(méi)有用逗給開(kāi)。 1.class class es6 中 為 關(guān)鍵字用來(lái)聲明 一個(gè) 類(lèi) 1.只能通過(guò)new調(diào)用 2.不存在變量提升 3.多個(gè)方法之間直接書(shū)寫(xiě),不需要,隔開(kāi) 4.類(lèi)的方法是直接定義在類(lèi)的原型上的 5.定義在類(lèi)中的方法不可枚舉 6.Ob...

    acrazing 評(píng)論0 收藏0
  • JS基礎(chǔ)入門(mén)篇(三十六)—面向對(duì)象( 三 )

    摘要:所以不會(huì)報(bào)錯(cuò)函數(shù)聲明可以先調(diào)用再聲明函數(shù)聲明解析時(shí),不會(huì)放到前面。所以會(huì)報(bào)錯(cuò)報(bào)錯(cuò)多個(gè)方法之間直接書(shū)寫(xiě)不需要隔開(kāi)我會(huì)說(shuō)話(huà)解析其中方法和方法之間并沒(méi)有用逗給開(kāi)。 1.class class es6 中 為 關(guān)鍵字用來(lái)聲明 一個(gè) 類(lèi) 1.只能通過(guò)new調(diào)用 2.不存在變量提升 3.多個(gè)方法之間直接書(shū)寫(xiě),不需要,隔開(kāi) 4.類(lèi)的方法是直接定義在類(lèi)的原型上的 5.定義在類(lèi)中的方法不可枚舉 6.Ob...

    MiracleWong 評(píng)論0 收藏0
  • JS基礎(chǔ)入門(mén)篇(三十六)—面向對(duì)象( 三 )

    摘要:所以不會(huì)報(bào)錯(cuò)函數(shù)聲明可以先調(diào)用再聲明函數(shù)聲明解析時(shí),不會(huì)放到前面。所以會(huì)報(bào)錯(cuò)報(bào)錯(cuò)多個(gè)方法之間直接書(shū)寫(xiě)不需要隔開(kāi)我會(huì)說(shuō)話(huà)解析其中方法和方法之間并沒(méi)有用逗給開(kāi)。 1.class class es6 中 為 關(guān)鍵字用來(lái)聲明 一個(gè) 類(lèi) 1.只能通過(guò)new調(diào)用 2.不存在變量提升 3.多個(gè)方法之間直接書(shū)寫(xiě),不需要,隔開(kāi) 4.類(lèi)的方法是直接定義在類(lèi)的原型上的 5.定義在類(lèi)中的方法不可枚舉 6.Ob...

    diabloneo 評(píng)論0 收藏0
  • 【連載】前端個(gè)人文章整理-從基礎(chǔ)到入門(mén)

    摘要:個(gè)人前端文章整理從最開(kāi)始萌生寫(xiě)文章的想法,到著手開(kāi)始寫(xiě),再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫(xiě)好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開(kāi)始萌生寫(xiě)文章的想法,到著手...

    madthumb 評(píng)論0 收藏0
  • JS基礎(chǔ)入門(mén)篇(三十四)— 面向對(duì)象(一)

    摘要:對(duì)象對(duì)象的定義對(duì)象是由鍵值對(duì)組成的無(wú)序集合。創(chuàng)建對(duì)象兩種方法方法一字面量方法方法二構(gòu)造函數(shù)創(chuàng)建面向?qū)ο蠛兔嫦蜻^(guò)程的比較如果想要把大象放進(jìn)冰箱。 1.對(duì)象 對(duì)象的定義 : 對(duì)象 是 由 鍵值對(duì) 組成的無(wú)序集合。 創(chuàng)建對(duì)象兩種方法 : 方法一 : 字面量方法 var obj = {name: k}; 方法二 : new Object( ) 構(gòu)造函數(shù)創(chuàng)建 var a = n...

    fantix 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<