亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Javascript面向?qū)ο蟮某绦蛟O(shè)計(jì)_理解對象

劉厚水 / 2815人閱讀

摘要:面向?qū)ο蟮某绦蛟O(shè)計(jì)理解對象前言最近在細(xì)讀高級程序設(shè)計(jì),對于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下??偨Y(jié)如果英語水平足夠好的話,建議看英文原版書籍或者國外大師的博客。

JS面向?qū)ο蟮某绦蛟O(shè)計(jì)_理解對象 前言:最近在細(xì)讀Javascript高級程序設(shè)計(jì),對于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。

如有紕漏或錯(cuò)誤,會非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaScript高級程序設(shè)計(jì)第三版》。

面向?qū)ο?Object-Oriented, OO)的計(jì)算機(jī)語言有一個(gè)標(biāo)志,就是它們都有一個(gè)類class的概念,通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對象。ECMAScript中沒有類的概念,因而它的對象也與基于類的計(jì)算機(jī)語言中的對象不同。

ECMA-262把對象定義為: “無序?qū)傩缘募希鋵傩钥梢园局?、對象或者函?shù)?!? 也就是說對象是一組沒有特定順序的值。對象的每個(gè)屬性或方法都有一個(gè)名字,而每個(gè)名字都映射(map)到一個(gè)值。所以我們可以把ECMAScript中的對象想象成散列表,換句話說,就是名值對,其中值可以是數(shù)據(jù)或者函數(shù)。每個(gè)對象都是基于引用類型創(chuàng)建的,這個(gè)值可以是原生類型,也可以是開發(fā)人員定義的類型。

理解對象

如果我們要創(chuàng)建自定義對象,最簡單的方式就是創(chuàng)建一個(gè)Object類型的實(shí)例對象,然后再為它添加屬性和方法。

//使用new關(guān)鍵字從Object類型中實(shí)例化出一個(gè)對象。

var person = new Object();
person.name = "Shaw";
person.age = "Secret";
person.job = "Front-end Engineer";
person.sayName = function(){
    console.log(this.name);
    // 這里的this指向person,call調(diào)用它的就是person
}

上述代碼,創(chuàng)建了一個(gè)person對象,并為它添加了三個(gè)屬性(name, age, job)和一個(gè)方法 sayName()。其中,sayName() 方法用于顯示this.name(被解析為person.name)的值。

現(xiàn)在,對象字面量成為創(chuàng)建這種對象的首選模式。

// 之前的例子,可以寫成這樣

var person = {
    name: "Shaw",
    age: "Secret",
    job: "Front-end Engineer",
    sayName: function(){
        console.log(this.name)
    }
}

這些屬性在創(chuàng)建時(shí)都帶有一些特性值(attribute ), Javascript通過特性來定義屬性(property)的行為。描述特性的字符叫做descriptor。

屬性特性 PropertyAttribute

特性(attribute)描述了屬性(property)的各種特征(也可以理解為特性值),ECMA-262第5版定義這些特性是為了實(shí)現(xiàn)JavaScript引擎用的,因此在JavaScript中不能直接訪問到它們。為了表示特性是內(nèi)部值, 該規(guī)范把它們放在兩對方括號中,[[Enumerable]]。

ECMAScript定義對象的屬性分為兩種:數(shù)據(jù)屬性和訪問器屬性。

對象屬性的數(shù)據(jù)特性

數(shù)據(jù)特性包含一個(gè)數(shù)據(jù)值的位置。在這個(gè)位置可以讀取和寫入值(I/O)。

數(shù)據(jù)特性的描述符(property attribute descriptor)

[[Configurable]], 可配置的: 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性或能否把屬性修改為訪問器屬性。像上面例子那樣直接在對象上定義的屬性,這些屬性的這個(gè)特性默認(rèn)值為true(可以刪改定義屬性)。

[[Enumerable]], 枚舉: 表示能否通過for-in循環(huán)返回屬性。像上面例子那樣直接在對象上定義的屬性,對象的屬性的這個(gè)Enumerable特性值默認(rèn)為true。

[[Writable]], 改寫: 表示能否修改屬性的值。像上面例子那樣直接在對象上定義的屬性,對象的屬性的這個(gè)writable特性值默認(rèn)為true。

[[value]], 輸入讀取屬性值:讀取屬性值的時(shí)候,從這個(gè)位置開始讀; 寫入屬性的時(shí)候,把新值保存在這個(gè)位置。這個(gè)特性的默認(rèn)值為undefined。

對于上面的那個(gè)例子中直接在對象上定義的屬性, 屬性們的特性值[[Configurable]]、[[Enumberable]]、[[Writable]]的默認(rèn)值都為true,而[[value]]特性被設(shè)置為指定的值。

//例子
var person = {
    name: "Shaw"
    //偽代碼
    //name: { value: "Shaw"}
};

//這里創(chuàng)建一個(gè)名為name的屬性,為它指定的值是"Shaw"
//也就是說, [[value]]特性被設(shè)置為“Shaw”,而對這個(gè)值的任何修改都將反應(yīng)在這個(gè)位置。

要修改屬性默認(rèn)的特性,必須使用ECMAScript5的Object.defineProperty()方法。 這個(gè)方法接收三個(gè)參數(shù): 屬性所在的對象、屬性的名字和一個(gè)描述符對象。 其中, 描述符(descriptor)對象的屬性必須是: configurable、enumerable、writable和value。 設(shè)置其中的一或多個(gè)值,可以修改對應(yīng)的特性值。請看下面的例子:

var person = {};

Object.defineProperty(person, "name", {
    writable: false,
    value: "Shaw"
});

console.log(person.name); //"Shaw"
person.name = "roc";
console.log(person.name); // 還是"Shaw", 因?yàn)橥ㄟ^Object.defineProperty()方法,設(shè)置該屬性的特性writable的值為false,即不可改寫。

這個(gè)例子創(chuàng)建一個(gè)名為name的屬性,它的值“Shaw"是不可改寫的,即只能讀取。如果嘗試為它指定新值,賦值操作會被忽略;在嚴(yán)格模式下,賦值操作會拋出錯(cuò)誤。

類似的規(guī)則也適用于屬性的可配置特性。例如:

var person = {};
Object.defineProperty(person, "name", {
    configurable: false,
    value: "Shaw"
});
delete person.name; // false, 因?yàn)閏onfigurable為false; 
console.log(person.name);

把屬性的特性configurable設(shè)置為false,意味著該屬性是不可配置的,也就是不能從對象中刪除這個(gè)屬性。如果對這個(gè)屬性調(diào)用delete, 在非嚴(yán)格模式下什么都不會發(fā)生, 在嚴(yán)格模式下, 會拋出一個(gè)錯(cuò)誤。 ==注意==, 一旦把屬性的特性定義為不可配置的,就不能再把它變回可配置了。此時(shí),再調(diào)用Object.defineProperty()方法,會拋出錯(cuò)誤。

var person = {};
Object.defineProperty(person, "name", {
    configurable: false,
    value: "Shaw"
    //不指定的話, 其余的特性值為默認(rèn)值,也就是說特性writable的默認(rèn)值為 false,
    //特性 enumerable的默認(rèn)值為 false
})

//Uncaught TypeError: Cannot redefine property: name
Object.defineProperty(person, "name", {
    configurable: true,
    value: "Shaw"
})

換句說,可以多次調(diào)用Object.defineProperty()方法來修改該屬性, 但是設(shè)置屬性的特性configurable的值為false(不可配置)后,其結(jié)果是不可逆的, 就會有限制了。

在調(diào)用Object.defineProperty()方法來創(chuàng)建一個(gè)新的屬性時(shí)候,如果不指定,configurable、writable、enumerable特性的默認(rèn)值都為false。

如果調(diào)用Object.defineProperty()方法只是修改已定義的屬性的特性, 則無此限制。 因?yàn)橐呀?jīng)定義的屬性的特性configurable、enumerable、writable默認(rèn)都為true。比如之前的那個(gè)例子:

var person = {
    name: "Shaw"
    // 偽代碼 
    /*propertyAttribute = {
        configurable(descriptor): true,
        enumerable(descriptor): true,
        writable(descriptor): true,
        value(descriptor): "Shaw"*/
    }
}

多數(shù)情況下, 我們可能都用不到Object.defineProperty()提供的這些高級功能。

不過,理解這些概念對理解JavaScript對象有很大的幫助。

對象屬性的訪問器特性

顧名思義就是定義了對象內(nèi)部,該屬性的特性是有權(quán)限訪問或設(shè)置對象內(nèi)部其他屬性。
訪問器屬性不包含數(shù)據(jù)值;它們包含一對兒getter和setter函數(shù)。

在讀取訪問器屬性時(shí),會調(diào)用getter函數(shù),這個(gè)函數(shù)負(fù)責(zé)返回有效的值; 在寫入訪問器屬性時(shí),會調(diào)用setter函數(shù)并傳入新值,這個(gè)函數(shù)負(fù)責(zé)如何處理數(shù)據(jù)。 訪問器屬性有如下4個(gè)特性:

[[configurable]],是否可配置。 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性。或者能否把屬性修改為數(shù)據(jù)屬性。對于直接在對象上定義的屬性, 這個(gè)屬性的該特性的默認(rèn)值為true。

[[Enumerable]], 是否可枚舉。 表示能否通過for-in循環(huán)返回屬性。 對于直接在對象上定義的屬性,這個(gè)屬性的該特性的默認(rèn)值為true。

[[Get]], 讀取屬性函數(shù)。 讀取屬性時(shí)調(diào)用的函數(shù)。默認(rèn)值為undefined。

[[Set]], 設(shè)置屬性函數(shù)。 設(shè)置屬性時(shí)調(diào)用的函數(shù)。默認(rèn)值為undefined。

訪問器屬性不能直接定義, 必須使用Object.defineProperty()來定義。

var cat = {
    _age: 1, 
    adoptionYear: 2016
};

Object.defineProperty(cat, "age", {
    get: function() {
        return this._age;
    },
    set: function(newAge) {
        if(newAge>1) {
            this._age = newAge; //5
            this.adoptionYear +=  newAge - 1;
        }
    }
});

window.alert(cat.age); //1
cat.age = 5;
window.alert(cat.age); //5
window.alert(cat.adoptionYear); // 2020

以上代碼創(chuàng)建了一個(gè)cat對象,并給它定義兩個(gè)默認(rèn)的屬性: _age和adoptionYear。 _age 是一種約定俗成的記號,表示只能通過對象屬性的訪問器特性方法才能訪問到的屬性(可以想象成對象的成員屬性)。 而屬性year的訪問器特性則包含一個(gè)get函數(shù)和set函數(shù)。get函數(shù)返回_age的值, set函數(shù)通過計(jì)算來確定貓咪的收養(yǎng)年份。因此,把a(bǔ)ge的屬性值修改為5,而adoptionYear變?yōu)?020,即已經(jīng)收養(yǎng)了四年。這是使用訪問器屬性的常見方法,即設(shè)置一個(gè)屬性的值然后改變另外一個(gè)屬性的值。

在這個(gè)定義對象屬性的訪問器特性之前,Object.defineProperty(object, "property", { get: function() {} , set: function(){}}) 。 要創(chuàng)建對象屬性的訪問器特性,一般都使用兩個(gè)非標(biāo)準(zhǔn)方法: __defineGetter__() 和 __defineSetter__(), ==注意這里是雙下劃線==。 這兩個(gè)方法最初是由Firefox引入的,后來Safari 3,Chrome 1和Opera9.5也給出相同的實(shí)現(xiàn)。 使用這兩個(gè)遺留的方法,也可以實(shí)現(xiàn)對象屬性的訪問器特性設(shè)置。

// 使用例子如下
var cat = {
    _age: 1,
    adoptionYear: 2016
}

cat.__defineGetter__("age", function(){
    return this._age;
});

cat.__defineSetter__("age", function(newAge){
    if(newAge > 1) {
        this._age = newAge;
        this.adoptionYear += this._age - 1;
    }
})

alert(cat.age); //1
alert(cat.adoptionYear); //2016
cat.age = 5;
alert(cat.age); //5
alert(cat.adoptionYear); //2020
同時(shí)定義對象多個(gè)屬性的特性的方法

為對象同時(shí)定義多個(gè)屬性特性的可能性很大,ECMAScript5又定義了一個(gè)Object.defineProperties(object, ObjectDescriptor)方法,用這個(gè)方法可以通過一次性定義對象的多個(gè)屬性特性。 該方法接收兩個(gè)對象參數(shù): 第一個(gè)對象參數(shù)是要添加和修改屬性特性值的對象,第二個(gè)對象參數(shù)的屬性與第一個(gè)對象中要添加或修改的屬性一一對應(yīng)。

// 還是代碼比較直觀

var cat = {};
Object.defineProperties(cat, {
    _name: {
        writable: true,
        value: "Meow"
    },
    _age: {
        writable: true,
        value: 1
    },
    adoptionYear: {
        writable: true,
        value: 1
    },
    age: {
        get: function() {
            return this._age;
        },
        set: function(newAge) {
            if(newAge <= 1) {
                this._age = 1;
            };
            this._age = newAge;
            this.adoptionYear += newAge -1;
        }
    }
})

alert(cat.age); // 1
cat.age = 3;
alert(cat.age); // 3
alert(cat.adoptionYear); // 3 從小就收養(yǎng)了。
讀取屬性的特性

ECMAScript5定義了Object.getOwnPropertyDescriptor(object, "property")方法, 該方法取得給定屬性的特性描述符。

這個(gè)方法接收兩個(gè)參數(shù):

第一個(gè)參數(shù)為: 屬性所在的對象。

第二個(gè)參數(shù)為: 需要讀取其特性值(PropertyAttribute) 的對象屬性。

該方法的返回值是一個(gè)對象,所以可以通過.語法讀取到值,如果是屬性的訪問器特性,返回的這個(gè)對象的屬性有:configurable、enumerable、get, set; 如果是數(shù)據(jù)屬性, 這個(gè)對象的屬性有configurable、enumerable、writable和value。

var person = {};
Object.defineProperties(person, {
    _name: {
        writable: true,
        value: "請使用person.name = ?,給我定義一個(gè)名字呀!"
    },
    _age: {
        writable: true,
        value: "請使用person.age = ?,給我定義一個(gè)年齡呀!"
    },
    _gender: {
        writable: true,
        value: "請使用person.gender = ?,給我定義一個(gè)性別呀!"
    },
    name: {
        get: function(){
            return this._name;
        },
        set: function(newName) {
            this._name = newName;
        }
    },
    age: {
        get: function(){
            return this._age;
        },
        set: function(newAge) {
            this._age = newAge;
        }
    },
    gender: {
        get: function(){
            return this._gender;
        },
        set: function(newGender) {
            this._gender = newGender;
        }
    }
});

var objPropAttrDescriptor = Object.getOwnPropertyDescriptor(person, "_age");
alert(objPropAttrDescriptor.value); //請使用person.gender = ?,給我定義一個(gè)性別呀!
alert(objPropAttrDescriptor.configurable); //false;
alert(typeof objPropAttrDescriptor.get); // undefined;

var objPropAttrDescriptor = Object.getOwnPropertyDescriptor(person, "age");
alert(objPropAttrDescriptor.value);// undefined;
alert(objPropAttrDescriptor.configurable); //false;
alert(typeof objPropAttrDescriptor.get); // function

在JavaScript中,可以針對任何對象 - 包括DOM和BOM對象,使用Object.getOwnPropertyDescript(object, "objProperty")方法,。

總結(jié)

如果英語水平足夠好的話,建議看英文原版書籍或者國外大師的博客。畢竟翻譯過來的文字,很多東西都變了味, 而且看英文,會讓你注意力更加集中,不容易跑神。

接下來我會定期翻譯一些國外的精品博客。 立個(gè)Flag,促使自己進(jìn)步。

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/98150.html

相關(guān)文章

  • 面向對象 JavaScript

    摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對象存在。而在基于原型的面向?qū)ο蠓绞街?,對象則是依靠構(gòu)造器利用原型構(gòu)造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長期以來人們對這一門語言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從對語言感悟的角度闡述為什...

    novo 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評論0 收藏0
  • JavaScript面向對象程序設(shè)計(jì)

    摘要:目錄導(dǎo)語理解對象和面向?qū)ο蟮某绦蛟O(shè)計(jì)創(chuàng)建對象的方式的繼承機(jī)制原型對象原型鏈與原型對象相關(guān)的方法小結(jié)導(dǎo)語前面的系列文章,基本把的核心知識點(diǎn)的基本語法標(biāo)準(zhǔn)庫等章節(jié)講解完本章開始進(jìn)入核心知識點(diǎn)的高級部分面向?qū)ο蟮某绦蛟O(shè)計(jì),這一部分的內(nèi)容將會對對象 目錄 導(dǎo)語 1.理解對象和面向?qū)ο蟮某绦蛟O(shè)計(jì) 2.創(chuàng)建對象的方式 3.JavaScript的繼承機(jī)制 3.1 原型對象 3.2 原型鏈 3.3 與...

    gitmilk 評論0 收藏0
  • 理解JavaScript核心知識點(diǎn):原型

    摘要:首先,需要來理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識。對于這樣的開發(fā)者來說 J...

    iKcamp 評論0 收藏0

發(fā)表評論

0條評論

劉厚水

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<