精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
JS高級應(yīng)用:談Javascript 閉包(2):對象屬性名解析

ECMAScript 認(rèn)可兩類對象:原生(Native)對象和宿主(Host)對象,其中宿主對象包含一個被稱為內(nèi)置對象的原生對象的子類(ECMA 262 3rd Ed Section 4.3)。原生對象屬于語言,而宿主對象由環(huán)境提供,比如說可能是文檔對象、DOM 等類似的對象。

原生對象具有松散和動態(tài)的命名屬性(對于某些實(shí)現(xiàn)的內(nèi)置對象子類別而言,動態(tài)性是受限的--但這不是太大的問題)。對象的命名屬性用于保存值,該值可以是指向另一個對象(Objects)的引用(在這個意義上說,函數(shù)也是對象),也可以是一些基本的數(shù)據(jù)類型,比如:String、Number、Boolean、Null 或 Undefined。其中比較特殊的是 Undefined 類型,因?yàn)榭梢越o對象的屬性指定一個 Undefined 類型的值,而不會刪除對象的相應(yīng)屬性。而且,該屬性只是保存著 undefined 值。

下面簡要介紹一下如何設(shè)置和讀取對象的屬性值,并最大程度地體現(xiàn)相應(yīng)的內(nèi)部細(xì)節(jié)。

值的賦予

對象的命名屬性可以通過為該命名屬性賦值來創(chuàng)建,或重新賦值。即,對于:

var objectRef = new Object(); //創(chuàng)建一個普通的 javascript 對象。

可以通過下面語句來創(chuàng)建名為 “testNumber” 的屬性:

objectRef.testNumber = 5;/* - 或- */objectRef["testNumber"] = 5;

在賦值之前,對象中沒有“testNumber” 屬性,但在賦值后,則創(chuàng)建一個屬性。之后的任何賦值語句都不需要再創(chuàng)建這個屬性,而只會重新設(shè)置它的值:

objectRef.testNumber = 8;/* - 或- */objectRef["testNumber"] = 8;

稍后我們會介紹,Javascript 對象都有原型(prototypes)屬性,而這些原型本身也是對象,因而也可以帶有命名的屬性。但是,原型對象命名屬性的作用并不體現(xiàn)在賦值階段。同樣,在將值賦給其命名屬性時,如果對象沒有該屬性則會創(chuàng)建該命名屬性,否則會重設(shè)該屬性的值。

值的讀取

當(dāng)讀取對象的屬性值時,原型對象的作用便體現(xiàn)出來。如果對象的原型中包含屬性訪問器(property accessor)所使用的屬性名,那么該屬性的值就會返回:

/* 為命名屬性賦值。如果在賦值前對象沒有相應(yīng)的屬性,那么賦值后就會得到一個:*/objectRef.testNumber = 8;/* 從屬性中讀取值 */var val = objectRef.testNumber;/* 現(xiàn)在, - val - 中保存著剛賦給對象命名屬性的值 8*/   

而且,由于所有對象都有原型,而原型本身也是對象,所以原型也可能有原型,這樣就構(gòu)成了所謂的原型鏈。原型鏈終止于鏈中原型為 null 的對象。Object 構(gòu)造函數(shù)的默認(rèn)原型就有一個 null 原型,因此:

var objectRef = new Object(); //創(chuàng)建一個普通的 JavaScript 對象。

創(chuàng)建了一個原型為 Object.prototype 的對象,而該原型自身則擁有一個值為 null 的原型。也就是說,objectRef 的原型鏈中只包含一個對象-- Object.prototype。但對于下面的代碼而言:

/* 創(chuàng)建 - MyObject1 - 類型對象的函數(shù)*/function MyObject1(formalParameter){    /* 給創(chuàng)建的對象添加一個名為 - testNumber -        的屬性并將傳遞給構(gòu)造函數(shù)的第一個參數(shù)指定為該屬性的值:*/    this.testNumber = formalParameter;}/* 創(chuàng)建 - MyObject2 - 類型對象的函數(shù)*/function MyObject2(formalParameter){   /* 給創(chuàng)建的對象添加一個名為 - testString -       的屬性并將傳遞給構(gòu)造函數(shù)的第一個參數(shù)指定為該屬性的值:*/    this.testString = formalParameter;}/* 接下來的操作用 MyObject1 類的實(shí)例替換了所有與 MyObject2 類的實(shí)例相關(guān)聯(lián)的原型。而且,為 MyObject1 構(gòu)造函數(shù)傳遞了參數(shù)- 8 - ,因而其 - testNumber - 屬性被賦予該值:*/MyObject2.prototype = new MyObject1( 8 );/* 最后,將一個字符串作為構(gòu)造函數(shù)的第一個參數(shù),創(chuàng)建一個 - MyObject2 - 的實(shí)例,并將指向該對象的引用賦給變量 - objectRef - :*/var objectRef = new MyObject2( "String_Value" );

被變量 objectRef 所引用的 MyObject2 的實(shí)例擁有一個原型鏈。該鏈中的第一個對象是在創(chuàng)建后被指定給 MyObject2 構(gòu)造函數(shù)的 prototype 屬性的 MyObject1 的一個實(shí)例。MyObject1的實(shí)例也有一個原型,即與 Object.prototype 所引用的對象對應(yīng)的默認(rèn)的 Object 對象的原型。最后, Object.prototype 有一個值為 null 的原型,因此這條原型鏈到此結(jié)束。

當(dāng)某個屬性訪問器嘗試讀取由 objectRef 所引用的對象的屬性值時,整個原型鏈都會被搜索。在下面這種簡單的情況下:

var val = objectRef.testString;

因?yàn)?nbsp;objectRef 所引用的 MyObject2 的實(shí)例有一個名為“testString”的屬性,因此被設(shè)置為“String_Value”的該屬性的值被賦給了變量 val。但是:

var val = objectRef.testNumber;

則不能從 MyObject2 實(shí)例自身中讀取到相應(yīng)的命名屬性值,因?yàn)樵搶?shí)例沒有這個屬性。然而,變量 val 的值仍然被設(shè)置為 8,而不是未定義--這是因?yàn)樵谠搶?shí)例中查找相應(yīng)的命名屬性失敗后,解釋程序會繼續(xù)檢查其原型對象。而該實(shí)例的原型對象是 MyObject1 的實(shí)例,這個實(shí)例有一個名為“testNumber”的屬性并且值為 8,所以這個屬性訪問器最后會取得值 8。而且,雖然MyObject1 和 MyObject2 都沒有定義 toString 方法,但是當(dāng)屬性訪問器通過 objectRef 讀取 toString 屬性的值時:

var val = objectRef.toString;

變量 val 也會被賦予一個函數(shù)的引用。這個函數(shù)就是在 Object.prototype 的 toString 屬性中所保存的函數(shù)。之所以會返回這個函數(shù),是因?yàn)榘l(fā)生了搜索objectRef 原型鏈的過程。當(dāng)在作為對象的 objectRef 中發(fā)現(xiàn)沒有“toString”屬性存在時,會搜索其原型對象,而當(dāng)原型對象中不存在該屬性時,則會繼續(xù)搜索原型的原型。而原型鏈中最終的原型是Object.prototype,這個對象確實(shí)有一個 toString 方法,因此該方法的引用被返回。

最后:

var val = objectRef.madeUpProperty;

返回 undefined,因?yàn)樵谒阉髟玩湹倪^程中,直至 Object.prototype 的原型--null,都沒有找到任何對象有名為“madeUpPeoperty”的屬性,因此最終返回 undefined

不論是在對象或?qū)ο蟮脑椭校x取命名屬性值的時候只返回首先找到的屬性值。而當(dāng)為對象的命名屬性賦值時,如果對象自身不存在該屬性則創(chuàng)建相應(yīng)的屬性。

這意味著,如果執(zhí)行像 objectRef.testNumber = 3 這樣一條賦值語句,那么這個 MyObject2 的實(shí)例自身也會創(chuàng)建一個名為“testNumber”的屬性,而之后任何讀取該命名屬性的嘗試都將獲得相同的新值。這時候,屬性訪問器不會再進(jìn)一步搜索原型鏈,但 MyObject1 實(shí)例值為 8 的“testNumber”屬性并沒有被修改。給 objectRef 對象的賦值只是遮擋了其原型鏈中相應(yīng)的屬性。

注意:ECMAScript 為 Object 類型定義了一個內(nèi)部 [[prototype]] 屬性。這個屬性不能通過腳本直接訪問,但在屬性訪問器解析過程中,則需要用到這個內(nèi)部 [[prototype]] 屬性所引用的對象鏈--即原型鏈。可以通過一個公共的 prototype 屬性,來對與內(nèi)部的 [[prototype]] 屬性對應(yīng)的原型對象進(jìn)行賦值或定義。這兩者之間的關(guān)系在 ECMA 262(3rd edition)中有詳細(xì)描述,但超出了本文要討論的范疇。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
理解 JavaScript 閉包
Javascript Closures (1)
javascript——prototype與
JS 原型的淺談
10、JS | 給已有的類原型添加屬性和方法
JavaScript 語言精粹的筆記
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 沛县| 财经| 诏安县| 濉溪县| 洱源县| 西安市| 舟山市| 麻栗坡县| 文登市| 读书| 清新县| 施甸县| 吉林省| 南宁市| 芦溪县| 娱乐| 淮南市| 分宜县| 古田县| 青铜峡市| 双桥区| 木里| 凉城县| 南城县| 界首市| 新野县| 织金县| 夏河县| 家居| 塔城市| 湘西| 文化| 亚东县| 沙田区| 徐水县| 绥芬河市| 滁州市| 霍林郭勒市| 军事| 南部县| 苍溪县|