JavaScript中的Objects,JavaScriptObjects
JavaScript中的Objects
在JavaScript中,建立Objects有兩種方式,declarative (literal) form和 constructed form。
首先,聲明式如下:
var myObj = { key: value // ...};
構造式如下:
var myObj = new Object();myObj.key = value;
聲明式與構造式建立的對象完全相同,只不過構造式的需要一個個地添加添加屬性,一般情況下我們都是採用聲明式的建立對象。
JavaScript中的原始類型
JavaScrip中有六種原始類型:
- string
- number
- boolean
- null
- undefined
- object
他們並不屬於物件類型,值得注意的是,null有時候被認為是物件類型,主要原因是typeof null的傳回值為object(該語言的bug),實際上,null屬於原始類型。
還有一種誤解
everything in JavaScript is an object
顯然這也是錯誤的。
物件類型中還有一些物件類型的子類型的( object sub-types),function是其子類型(專業術語稱之為callable object),在JavaScript被認作是第一等的(first class),相比一般對象,function具有調用屬性(callable behavior),還有一種物件類型的子類型為數組(Arrays ),相比一般對象,其內容更結構化。
JavaScript中還有一些內建對象的子類型,我們稱之為內建對象(built-in objects),有如下幾種:
- String
- Number
- Boolean
- Object
- Function
- Array
- Date
- RegExp
- Error
這些內建對象表現出來的特性甚至與Java中的class的特性一致,實際上,它們都是內建函數(built-in functions),這些內建函數都被用作構造器(constructor ),關於JavaScript 中的構造器,
傳統的物件導向的語言中,構造器屬於class的特殊方法,當我們使用new執行個體化一個類時,其構造器被調用,JavaScript 中的構造器與此很不同,JavaScript 中的構造器只是一般的函數(functions ),其恰好在函數前面使用了new操作符,它們與class無關,也不是用來執行個體化一個類,它們只是一個很普通的函數,只不過被new操作符 控制 調用了而已,它們不是constructor functions,只是construction calls of functions而已。
var strPrimitive = "I am a string";typeof strPrimitive; // "string"strPrimitive instanceof String; // falsevar strObject = new String( "I am a string" );typeof strObject; // "object"strObject instanceof String; // true// inspect the object sub-typeObject.prototype.toString.call( strObject ); // [object String]
strPrimitive屬於原始類型,strObject 屬於物件類型,當我們如果要檢查strPrimitive的長度,擷取其內容時,我們需要String類型的對象類完成操作。
幸運的是,當我們將原始類型的string轉化(coerces )為物件類型的String時,這些操作都被自動完成了,因此,一般來說,我們並不需要建立物件類型的變數,只需建立其對應的原始類型的變數即可,在需要時,JavaScript會自動幫我們轉化為對應的物件類型。
var strPrimitive = "I am a string";console.log( strPrimitive.length ); // 13console.log( strPrimitive.charAt( 3 ) ); // "m"
null 和undefined沒有相應的物件類型,Date 類型沒有對應的原始類型,Object, Array, Function, 和RegExp,無論我們使用literal還是使用constructor方式構建,其均為物件類型。
Error對象我們一般很少建立,其都是在出現異常時自動建立。
一般來說,對象中的內容不一定儲存在對象內部,其主要依賴於瀏覽器的實現,很多情況下,他們並不儲存在對象容器中,真正儲存在對象中的是對象的屬性名稱,他們主要用來作為引用指向他們對應的值的地方。
var myObject = { a: 2};myObject.a; // 2myObject["a"]; // 2
使用 . 操作符的其名稱與使用[""]的區別是後者可以使用UTF-8/unicode相容的屬性名稱,如[“Super-Fun!”],而前者則不可以通過. 操作符獲得對應的屬性值。
對象的屬性名稱都是string類型,我們可以通過變數的值來作為指向對象屬性值的地址:
var wantA = true;var myObject = { a: 2};var idx;if (wantA) { idx = "a";}// laterconsole.log( myObject[idx] ); // 2
由於對象的屬性名稱都是sting類型,如果不是string類型,JavaScript首先將其轉化為string類型,我們在使用時要注意這一點:
var myObject = { };myObject[true] = "foo";myObject[3] = "bar";myObject[myObject] = "baz";myObject["true"]; // "foo"myObject["3"]; // "bar"myObject["[object Object]"]; // "baz"
ES6中我們可以使用myObject[..]這種文法來計算出對象的屬性名稱:
var prefix = "foo";var myObject = { [prefix + "bar"]: "hello", [prefix + "baz"]: "world"};myObject["foobar"]; // hellomyObject["foobaz"]; // world
這種計算對象屬性名稱主要是用在Symbol(new primitive data type which has an opaque unguessable value, technically a string value)上,對象中的函數同樣也是不屬於對象本身,其擷取與屬性的擷取沒有什麼不同。
對於數組,我們需要注意的是,當我們向數組中添加屬性時,如果該屬性是數字類型的話,那麼將作為數組的元素添加到數組中,而不是像一般的屬性添加到數組對象中去:
var myArray = [ "foo", 42, "bar" ];myArray["3"] = "baz";myArray["a"]="a";myArray.length; // 4myArray[3]; // "baz"myArray.a; //"a"
ES5中,對象的屬性可以通過 property descriptor來進行描述:
var myObject = { a: 2};Object.getOwnPropertyDescriptor( myObject, "a" );// {// value: 2,// writable: true,// enumerable: true,// configurable: true// }
對象的屬性有三個特徵:writable, enumerable, 和configurable,他們的預設值如上例所示。我們可以Object.defineProperty(..)來為對象新添加一個屬性,或者修改對象屬性(如果是configurable的):
var myObject = {};Object.defineProperty( myObject, "a", { value: 2, writable: true, configurable: true, enumerable: true} );myObject.a; // 2
當writable=false,相當於其對象沒有setter方法:
var myObject = {};Object.defineProperty( myObject, "a", { value: 2, writable: false, // not writable! configurable: true, enumerable: true} );myObject.a = 3;myObject.a; // 2
如果在strict mode下,則會報錯:
"use strict";var myObject = {};Object.defineProperty( myObject, "a", { value: 2, writable: false, // not writable! configurable: true, enumerable: true} );myObject.a = 3; // TypeError
configurable=false是單向操作,無法復原:
var myObject = { a: 2};myObject.a = 3;myObject.a; // 3Object.defineProperty( myObject, "a", { value: 4, writable: true, configurable: false, // not configurable! enumerable: true} );myObject.a; // 4myObject.a = 5;myObject.a; // 5Object.defineProperty( myObject, "a", { value: 6, writable: true, configurable: true, enumerable: true} ); // TypeError
需要注意的一點是,當configurable=false時,我們可以配置writable的值從true到false,但是不能從false到true。
configurable=false還有一個作用就是阻止我們使用delete操作符刪除該屬性。
var myObject = { a: 2};myObject.a; // 2delete myObject.a;myObject.a; // undefinedObject.defineProperty( myObject, "a", { value: 2, writable: true, configurable: false, enumerable: true} );myObject.a; // 2delete myObject.a;myObject.a; // 2
對於enumerable,主要是用來控制for..in迴圈中是否可顯示。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。