getter 和 setter: 1、ES5 里,屬性值可以用一個或兩個方法代替,這兩個方法就是 getter 和 setter,它們使用 get 和 set 進行定義而不是通過 function 2、由 getter 和 setter 定義的屬性稱作 “存取器屬性”,它不同於“數據屬性”,數據屬性 ...
getter 和 setter:
1、ES5 里,屬性值可以用一個或兩個方法代替,這兩個方法就是 getter 和 setter,它們使用 get 和 set 進行定義而不是通過 function
2、由 getter 和 setter 定義的屬性稱作 “存取器屬性”,它不同於“數據屬性”,數據屬性只有一個簡單的值
3、當查詢存取器屬性的值時,JavaScript 調用 getter 方法(無參),並由它返回屬性存取表達式的值
4、當設置一個存取器屬性的值時,JavaScript 調用 setter 方法,並將賦值表達式右側的值當作參數傳給 setter
let obj = { x: 1, y: 1, // 註意 getter 和 setter 沒有使用冒號,但函數體結束和下一個方法或數據屬性之間有逗號隔開 // 設置一個可讀寫屬性 result get result() { return this.x+"+"+this.y+"i"; }, set result(arr) { // 需要參數 if (arr.length != 2) throw RangeError(); this.x = arr[0]; this.y = arr[1]; }, // 設置一個只寫屬性 add set add(arr) { if (arr.length != 2) throw RangeError(); this.x += arr[0]; this.y += arr[1]; return this.x+"+"+this.y+"i"; } } console.log(obj.result); // 使用 getter,輸出 1+1i obj.add = [1, 2]; // 使用 setter console.log(obj.result); // 輸出 2+3i obj.result = [3, 4]; console.log(obj.result); // 輸出 3+4i
註:讀取只寫屬性總是返回 undefined
屬性的特征:
1、除了包含名字和值之外,屬性還包含一些標識它們可寫、可枚舉和可配置的特性
2、數據屬性的 4 個特性:值、可寫性、可枚舉性和可配置性
3、存取器特性:讀取、寫入、可枚舉和可配置
4、數據屬性的描述符對象:value、writable、enumerable 和 configurable;存取器屬性則用 get 和 set 屬性代替 value 和 writable
5、writable、enumerable 和 configurable 都是布爾值,而 get 和 set 是函數值
6、通過 Object.getOwnPropertyDescriptor(obj, p) 可獲得某個對象特定屬性的屬性描述符
7、通過 Object.defineProperty(obj, p, attr) 設置或新建屬性的特性,Object.defineProperties(obj, map) 修改或新建多個屬性特性
8、Object.getOwnPropertyDescriptor() 和 Object.defineProperty() 都不能修改繼承來的屬性
// 通過 Object.getOwnPropertyDescriptor() 可獲得某個對象特定屬性的屬性描述符 console.log(Object.getOwnPropertyDescriptor({x: 1}, "x")); console.log(Object.getOwnPropertyDescriptor({}, "toString")); // undefined // defineProperty(obj, p, attr) 設置、新建屬性 // defineProperties(obj, map) let o = {}; // 新建多個屬性特性 Object.defineProperties(o, { x: {value: 1, writable: false, enumerable: true}, y: {value: 2, enumerable: true}, z: {value: 3, configurable: true, enumerable: true} }); console.log(Object.getOwnPropertyDescriptor(o, "x")); console.log(o.x); // 把它修改成可修改的 Object.defineProperty(o, "x", {writable: true}); console.log(Object.getOwnPropertyDescriptor(o, "x"));
對象的三個屬性:
1、原型屬性:在實例對象創建之初就設置好的,用來繼承屬性的,可通過將對象作為參數傳入 Object.getPrototypeOf() 來查詢它的原型
2、類屬性:是一個字元串,用以表示對象的類型信息,只有一種間接方法可以查詢它(toString())
3、可擴展性:用以表示是否可以給對象添加新屬性,通過將對象傳入 Object.isExtensible(),來判斷該對象是否可擴展;通過將對象傳入 Object.preventExtensions() 把其轉換為不可擴展(無法轉換回可擴展);Object.seal() 除了能將對象設置為不可擴展,還可以將對象的所有自有屬性都設置為不可配置;Object.isSealed() 來檢測對象是否封閉;Object.freeze() 將對象設置為不可擴展和屬性不可配置,同時將自有的所有數據屬性設置為只讀,存取器屬性(setter)不受影響
console.log(Object.getPrototypeOf(o)); // 輸出 o 的原型 {} console.log(Object.prototype.toString.call(o).slice(8, -1)); // 輸出 "Object" console.log(Object.prototype.toString.call([]).slice(8, -1)); // 輸出 "Array" console.log(Object.isExtensible(o)); // 判斷對象 o 是否可擴展,輸出 true Object.preventExtensions(o); // 將對象轉換為不可擴展 console.log(Object.isExtensible(o)); // 輸出 false
序列化對象:
1、我們可以將對象的狀態轉換為字元串,也可以將字元串還原為對象,ES5 提供了內置函數 JSON.stringify() 和 JSON.parse() 來序列化和還原對象
2、JSON 的語法是 JavaScript 語法的一個子集,它並不能表示 JavaScript 里所有的值
3、JSON.stringify() 只能序列化對象可枚舉的自有屬性
// 若屬性里有不可枚舉的,則不把它進行轉換 let str = JSON.stringify(o); // 輸出 contend: '{"x": 1, "y": 2, "z": 3}' type: string console.log("contend:", str, "\t type: ", typeof str); let ser = JSON.parse(str); // 轉換成對象 // 輸出 contend: {x: 1, y: 2, z: 3} type: object console.log("contend:", ser, "\t type: ", typeof ser);
對象方法:
1、toString() 方法:無參,返回一個表示調用這個方法的對象值的字元串
2、toLocaleString() 方法:返回一個表示這個對象的本地化字元串
3、toJSON() 方法:如果在待序列化的對象中存在這個方法,則調用它,返回一個序列化結果,而不是原始對象
4、valueOf() 方法:將對象轉換為某種原始值而非字元串
console.log(o.toString().slice(8, -1)); console.log(o.toLocaleString().slice(8, -1)); try { o.toJSON(); } catch(e) { // 若 toJSON 並未被定義,則會產生 TypeError console.log("TypeError"); } console.log(o.valueOf());