JavaScript高程讀書(shū)筆記-面向?qū)ο笤O(shè)計(jì)

一、理解對(duì)象

1、什么是對(duì)象
面向?qū)ο螅∣bject-Oriented,OO),ECMA中對(duì)象定義是:無(wú)序?qū)傩缘募?,其屬性可以包含基本值、?duì)象或者函數(shù)。其實(shí)簡(jiǎn)單理解,人可以就是一個(gè)對(duì)象,人包含著很多屬性,比如年齡age、體重weight、身高h(yuǎn)eight。
簡(jiǎn)單的創(chuàng)建一個(gè)對(duì)象可以如下:

var person = {
    name: "John",
    age: 29,
    job: "software Engineer",
    
    sayName: function(){
        alert(this.name);
    }
};

上面person就是一個(gè)簡(jiǎn)單的對(duì)象
2、對(duì)象屬性
對(duì)象有兩種屬性:數(shù)據(jù)屬性和訪問(wèn)器屬性

  • 數(shù)據(jù)屬性
    數(shù)據(jù)屬性包含一個(gè)數(shù)據(jù)值的位置,一共有4個(gè):
    1)、configurable:表示能否通過(guò)delete刪除屬性,默認(rèn)值為true
    2)、enumerable:表示能否通過(guò)for-in循環(huán)返回屬性,默認(rèn)值為true
    3)、writable:表示能否修改屬性的值,默認(rèn)為true
    4)、value:表示這個(gè)屬性的數(shù)據(jù)值
    修改默認(rèn)屬性,必須使用Object.defineProperty()方法,此方法接受3個(gè)參數(shù)
    Object.defineProperty(屬性所在的對(duì)象,屬性名字,描述對(duì)象),簡(jiǎn)單例子如下
var person = {};
Object.defineProperty(person,"name",{
    writable : fasle,
    value : "John"
});
alert(person.name) //"John"
person.name = "Greg"http://重新修改數(shù)據(jù)屬性
alert(person.name) //"John",設(shè)置了writable,因此無(wú)法修改

上述例子修改了writable屬性,導(dǎo)致對(duì)象屬性name不能重寫(xiě)!數(shù)據(jù)屬性雖然不常用,了解還是必須的

  • 訪問(wèn)器屬性
    訪問(wèn)器屬性包含一對(duì)getter和setter函數(shù)。當(dāng)我們調(diào)用對(duì)象屬性時(shí)候比如person.name,就是用get函數(shù),設(shè)置對(duì)象時(shí)候會(huì)調(diào)用setter屬性,修改訪問(wèn)器屬性例子:
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 = 2005//設(shè)置值
book.edition;//2

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

  • 工廠模式
    工廠模式,字如其意,就是類(lèi)似于工廠的工作方式,需要重復(fù)同樣的工作,比如為每個(gè)產(chǎn)品都要貼上名稱,出產(chǎn)日期等屬性。由于ECMA無(wú)法創(chuàng)建類(lèi),就用函數(shù)的方法類(lèi)封裝特定接口創(chuàng)建對(duì)象細(xì)節(jié),如下例子:
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("Trick",29,"SoftWare Engineer");
var person2 = createPerson("John",23,"Doctor");
  • 構(gòu)造函數(shù)模式
    使用構(gòu)造函數(shù)模式編寫(xiě)前面的例子如下:
function Person(name,age,job){
    this.name = name;
    this.job = job;
    this.age = age;
    this.sayName = function(){
        alert(this.name);
    };
}
var person1 = new Person("Trick",29,"SoftWare Engineer");
var person2 = new Person("John",23,"Doctor");

與上面的工廠模式區(qū)別有下:
1、沒(méi)有顯示地創(chuàng)建對(duì)象
2、直接將屬性和方法賦給this對(duì)象
3、沒(méi)有return語(yǔ)句
要新建一個(gè)新的Person實(shí)例,必須使用new操作符,按如上方法會(huì)經(jīng)歷以下4個(gè)步驟:
1、創(chuàng)建一個(gè)新的對(duì)象
2、將構(gòu)造函數(shù)的作用域賦給新的對(duì)象(也就是代碼中的this指向了這個(gè)新的對(duì)象)
3、執(zhí)行構(gòu)造函數(shù)的代碼(添加新的屬性)
4、返回新的對(duì)象
構(gòu)造函數(shù)缺陷:每個(gè)方法都要在實(shí)例上重新創(chuàng)一遍,這樣創(chuàng)建兩個(gè)完成同樣任務(wù)的function實(shí)例沒(méi)必要,比如:

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = new Function("alert(this.name)");
}

以上面這種方式創(chuàng)建的函數(shù),會(huì)導(dǎo)致不同的作用域鏈和標(biāo)識(shí)符解析,所以不同實(shí)例上的同名函數(shù)是不相等的
alert(person1.sayName == person2.sayName); //false
可以把sayName函數(shù)移到外面上來(lái)

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
}

但,我定義了一個(gè)全局函數(shù),可是只被某個(gè)對(duì)象調(diào)用,這樣如果一個(gè)對(duì)象有很多方法,那我就要?jiǎng)?chuàng)建很多全局函數(shù),這樣這個(gè)引用類(lèi)型毫無(wú)封裝性了,于是有原型模式來(lái)解決這個(gè)問(wèn)題。

  • 原型模式
    當(dāng)創(chuàng)建一個(gè)函數(shù)的時(shí)候,都會(huì)有一個(gè)prototype屬性,即原型屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象。簡(jiǎn)單來(lái)說(shuō),實(shí)例化一個(gè)對(duì)象后,這個(gè)實(shí)例可以調(diào)用該構(gòu)造函數(shù)原型對(duì)象上的屬性和方法。也就是說(shuō),上面提到的構(gòu)造函數(shù)是在里面定義實(shí)例信息,而原型模式是是將這些信息直接添加到原型的對(duì)象上,同樣簡(jiǎn)單的例子:
function Person(){}
Person.prototype.name = "John";
Person.prototype.age = 24;
var person1 = new Person()//實(shí)例化對(duì)象
person1.age //24

1、理解原型對(duì)象
無(wú)論什么時(shí)候,只要?jiǎng)?chuàng)建一個(gè)函數(shù)之后,就會(huì)為該函數(shù)創(chuàng)建一個(gè)prototype屬性,該屬性指向函數(shù)的原型對(duì)象。默認(rèn)下,所有原型對(duì)象會(huì)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性,這屬性又包含了一個(gè)指向prototype屬性所在函數(shù)的指針。

每當(dāng)代碼讀取某個(gè)對(duì)象某個(gè)屬性時(shí),首先從實(shí)例本身開(kāi)始,如果找到了則返回,如果沒(méi)找到,則繼續(xù)搜索指針指向的原型對(duì)象
hasOwnProperty() -- 該方法可以檢測(cè)一個(gè)屬性是存在于實(shí)例中還是在原型中,當(dāng)存在于實(shí)例中的時(shí)候才返回true。
2、原型和In操作符
使用In操作符會(huì)在通過(guò)對(duì)象能夠訪問(wèn)給定屬性時(shí)返回true,無(wú)論屬性存在于實(shí)例還是原型中

var person = new Person();
alert("name" in person)//true
person.name = "John";
alert("name" in person)//true

這樣,可以結(jié)合上面所說(shuō)的hasOwnProperty,可以確認(rèn)該屬性到底是存在對(duì)象還是在實(shí)例中

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

3、更簡(jiǎn)單的原型方式

function Person(){}
Person.prototype = {
    name : "John",
    age: 29,
    job: "Soft",
    sayName: function(){
        alert(this.name);
    }
}

4、原型對(duì)象的問(wèn)題缺點(diǎn)
共享同一套屬性是原型對(duì)象的優(yōu)點(diǎn),對(duì)于函數(shù)來(lái)說(shuō)很適合,但是對(duì)于屬性來(lái)說(shuō)就不適合。簡(jiǎn)單來(lái)看個(gè)例子

function Person(){}

Person.prototype = {
    constructor: Person,
    name: "Trick",
    age: 22,
    friends: ["John","Bob"]
}

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

person1.friends.push("Van");

person1.friends;//John,Bob,Van
person2.friends;//John,Bob,Van

可見(jiàn),我們Van只是person1的好友,可是當(dāng)把屬性push進(jìn)去后,修改了friends屬性,由于這個(gè)屬性是在原型對(duì)象上,因此person2的原型指針也指向了修改后的數(shù)組,這是我們所不想的情況,因此,后面出現(xiàn)了組合使用構(gòu)造函數(shù)模式和原型模式

  • 組合使用構(gòu)造函數(shù)模式和原型模式
    構(gòu)造函數(shù)模式用于定義實(shí)體屬性,而原型模式用于定義方法和共享屬性,例子:
function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["John","Counr"];
}
Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
}

以上只是讀高程面向?qū)ο笳鹿?jié)后所做的筆記,比較基礎(chǔ)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容