搜尋
首頁web前端js教程JavaScript中物件屬性詳解

JavaScript中物件屬性詳解

Nov 28, 2019 pm 05:37 PM
js物件屬性

JavaScript中物件屬性詳解

JavaScript 中的物件概念的確很容易讓人困惑。看下面一個例子:

var strPrimitive = "I'm mamacat";
typeof strPrimitive; // "string"
strPrimitive instanceof String; // false

var strObject = new String("I'm mamacat");
typeof strObject; // "object"
strObject instanceof String; // true

strPrimitive.substr(8, 3); // "cat"

同樣的字串賦值到對象,一會兒是字符串類型一會兒是對象,而明明不是對象類型的變數還是可以使用對象屬性,為什麼會這樣呢?

【相關課程推薦:JavaScript影片教學】  

#類型與內建物件

##JavaScript 中一共有六種主要(語言)類型,即 

string, number, boolean, null, undefined 和 object,其中前五個基本類型都不是物件(對 null 進行typeof 得到的是"object",這是語言本身的BUG)。而在此之外,則有許多特殊的物件子類型,例如陣列、函數和內建物件等。

有些內建物件的名字看著和簡單基本型別一樣,就例如 String,Boolean,Object 之類。這些內建物件從表現形式看就和別的物件導向語言中的「類別」概念差不多,而正如上篇文章所屬,它們實際上使只是一些能被用來建構一個對應子類型的內建函數而已(不要困惑,函數也是對象,這裡不矛盾)。於是就可以回到最初的例子,strObject 是內建函數/內建物件 String 所建構的變量,對應 String 子型,所以它是一個對象,而 strPrimitive 則是一個原始字面值而已。

當然,上面範例中最下面我們看起來對 strPrimitive 呼叫了 substr() 函數,這裡則是因為,JavaScript 引擎會在需要時,把原始字面量轉換成對應的對象,而轉換之後我們自然就可以使用屬性來存取對應的方法了。

物件屬性

那麼,就上方的例子而言,String 物件實例就會有substr() 函數可以用,但根據先前的文章可以知道,這些「函數」本身並不屬於某個對象,而這些函數實質是對應對象的屬性。當然,即便我們說某種類型的物件本身俱備各種屬性,實際上這些屬性也多是各自獨立存在的,只不過以引用的形式關聯在了一起而已,這和之前了解的內容也不矛盾。這些被關聯起來的東西,被稱為物件的 屬性。

物件的複製

插播一條快報,儘管之前的文章提到過,上方也又一次反覆強調過屬性只是以引用的形式關聯起來的獨立存在,我們有時仍然會「理所當然」的認為屬性是物件的一部分,而最容易因此踩坑的地方之一就是物件的複製了。仔細思考即可知道,當我們複製物件時,由於其屬性本身只是引用關聯,故「複製」得到的物件所包含的屬性引用指向的和原本物件的屬性引用其實還是同一個位置:

var ori = { a : 1};
var ori_copy = ori;
ori.a = 61;
ori_copy.a; // 61

顯然這很可能和我們的期望不一樣,而我們想要真正的拷貝物件則沒有完美適用性的方案,很多時候的常規做法則是把物件序列化一下,然後再以此反序列化得到新的物件來實現物件的拷貝(例如使用json)。 ES6 中新增了

Object.assign() 來進行物件的淺拷貝,做法是把物件的所有可枚舉屬性等號賦值到新物件中。不過仍需注意的是,等號賦值並不會賦值屬性的元資訊(屬性描述符,後述),在需要的情況下應特別留意。

屬性存取和數組

訪問物件所關聯的屬性的方式即透過. 或[] 運算子進行訪問,obj.a 和obj["a" ] 訪問的屬性實質上是一樣的,而這兩種訪問形式的區別也只有訪問的屬性名稱裡能不能有奇怪的符號而已。 [] 運算子內丟的是個字串,其實屬性名稱也永遠都是字串。當然,這個概念可能比較意外的就是,數組的下標存取其實並不是例外,數字還是被轉換成了字串才被使用的。

// 对象的属性访问:
var tejilang = {1 : "Teji Wolf"};
tejilang instanceof Array; // false
tejilang["1"]; // "Teji Wolf"
tejilang[1]; // "Teji Wolf"

// 这回保证它是 Array
var macat = ["codingcat"];
macat instanceof Array; // true
macat.length; // 1
macat[0]; // "codingcat"
macat["0"]; // "codingcat"
macat.length = 20;
macat; // (20) ["codingcat", empty × 19]

数组下标既然不属例外情况,那数组对象必然有其它属性控制数组本身的行为,例如上例中,macat 数组的长度就是 length 属性所体现的,通过修改它的值也就改变了对象本身对外的表现形式。当然,由于数组本身就是对象,所以我们还是可以把数组当键值对来用,只是这种做法通常是没有意义且会让人感到困惑的。JavaScript 引擎通常都根据对象的类型做了不同程度的优化,故除了代码逻辑可读性外,合理的使用也是多少可以改善性能的。

能够通过字符访问属性还是存在一些别的好处的,比如 ES6 的可计算属性名。当然 ES6 不在本文的关注范围内,所以这里就不再讨论了。

属性描述符

有时我们可能不希望某个属性被随意修改,有时候我们需要额外配置一些属性的信息,自 ES5 起,所有的属性就都具备了“属性描述符”(Property Descriptor)来控制属性本身的这些元信息。

数据描述符

来看这个例子:

var chris = {};
Object.defineProperty(chris, "IQ", {
    value: 228,
    writable: false,
    configurable: true,
    enumerable: true
});
chris.IQ = 61; // 静默失败了,如果是严格模式则会 TypeError
chris.IQ; // 228

通过 defineProperty 可以对一个对象的属性配置其对应的属性描述符(元信息),而属性描述符则包含访问描述符和数据描述符,上面的例子中,defineProperty 的第三个参数就定义了数据的若干数据描述符,其中 writable 表示可写,configurable 表示属性是否可配置(注意,修改成不可配置是单向操作),enumerable 则表示属性是否应当出现在枚举中,比如 for..in 中。

显然我们可以通过属性描述符实现对属性的保护,而同时也存在一些方便函数来做近似的事。如 Object.preventExtensions() 会保留原有属性但禁止添加新属性,Object.seal() 会密封对象,在禁止添加新属性的基础上把原有属性标记为不可配置,Object.freeze() 会冻结对象,即在密封的基础上把数据访问属性标记为不可写。

[[Get]], [[Put]] 和访问描述符

在我们访问和赋值一个对象的属性时,实际上是通过 [[Get]] 和 [[Put]] 操作进行的,例如属性访问时,[[Get]] 会先找有没有这个属性,如果没有则会遍历对象的 [[Prototype]] 链(原型链,这次不谈这个概念)来找,实在找不到则返回 undefined 。而这个行为实际是允许我们通过设置 getter (get())和 setter (set())函数来改变的,它们被称为 访问描述符。

当我们提供访问描述符时,对应的访问操作就不再受到 value writable 属性的影响了,另外需要注意的是,尽管它们也是属性描述符,但定义 getter 和 setter 并不要求一定要通过 defineProperty 设置:

var obj = {
    get a() { // 给 a 属性定义 getter
        return this._a_;
    },
    set a(val) { // a 属性的 setter
        this._a_ = val * 2;
    }
}

obj.a = 2;
obj.a; // 4

属性存在性

因为属性的值也可能是 undefined,不存在的属性直接访问得到的也是 undefined,所以直接通过简单的属性访问是无法区分是否存在的,这时我们即可通过 in 或者 hasOwnProperty() 检查属性是否存在对象中了:

var obj = {a : 2};
"a" in obj; // true
obj.hasOwnProperty("a"); // true

尽管仍没有讲到原型链的概念,这里仍然应注意,in 操作符会检查原型链中是否存在属性,而 hasOwnProperty 则不会。另外在一些情况下,有的对象会没有 hasOwnProperty 这个属性(此处不提原因),这时可以用过 Object.prototype.hasOwnProperty.call(objName, propertyName) 来实现检查。

本文来自 js教程 栏目,欢迎学习!  

以上是JavaScript中物件屬性詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:博客园。如有侵權,請聯絡admin@php.cn刪除
Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),