文章目錄
- 1.合并對象 - Object.assign()
- 介紹
- 進階
- 注意
- 用途
- 2.定義對象 - Object.defineProperty(obj, prop, descriptor)
- 3.新數據類型- Symbol
- 定義
- 應用
1.合并對象 - Object.assign()
介紹
- assign方法可以將多個對象(字典),語法:Object.assign(srcObj,obj1,obj2…)
- 對于重復的鍵將會被覆蓋(尤其注意對象被覆蓋),對于可枚舉(迭代)參數(被合并對象)若不是對象則自動轉換成對象合并(如string,[]),對于不可枚舉參數(undefined,null)會自動跳過。
- 若源對象(第一個參數)不可枚舉則會報錯
let srcObj= { a: 'a',b:'b',obj:{title:"我要被覆蓋了"} },
obj1 = { b: 2 },
obj2 = { c: 3 },
str3 = "字符串",
num4 = 5;
obj = {newTitle:"我是新的title"} // 1.合并、重復覆蓋、自動轉換成對象合并、自動跳過舉例:
console.log(Object.assign(srcObj, obj1 , obj2, str3, num4,obj));
// {a:'a',b:'2',c:3,0: "字",1: "符",2: "串",obj:{newTitle:"我是新的title"}}// 2.報錯
Object.assign(null, obj1 , obj2 ))
進階
- 當聲明一個對象時,它的enumerable屬性默認是true,我們也可以顯示的將它設為false,所以說對象不一定都是可迭代的(眼見不一定為實),但可以通過’.'取到。
- 若拷貝類型是Symbol 類型也會被拷貝。Symbol :和int、float等一樣是數據類型,只不過他是隱藏類型,直接訪問是取不到的
// 1.跳過不可迭代的對象
var unEnumer = Object.defineProperty({}, "k", {enumerable: false,value: "hello"}), // {k:"hello"}// 這樣定義對象,任何值都能作為鍵(被視為字符串)enumer = Object.defineProperty({}, null,{enumerable: true,value: "hello"}) // {"null":"hello"}
console.log(Object.assign( { b: "c" },unEnumer ,enumer ));
// {b: "c",null: "hello"}// 2.合并Symbol 類型,既可以當鍵也可以當值console.log(Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' },{'e':Symbol('f')}))
// {a: "b", e: Symbol(f), Symbol(c): "d"}
注意
- 拷貝后的數據間的影響關系
- 拷貝對象是數組則按照字典處理,數組很好理解成字典,如[‘a’,‘b’,‘c’],實際上會自動分配鍵,等價于{0:‘a’,1:‘b’,2:‘c’},所以處理規則同字典一樣。
- 對取值函數與賦值函數的處理
// 1.影響關系
var obj1 = { a: 1 },obj2={b:{c:1}};
var obj = Object.assign({}, obj1,obj2);
obj1.a = 2 // 不影響
obj2.b.c = 3 // 影響
console.log(obj,obj1,obj2) // {a: 1,b: {c: 3}}// 2.處理數組
console.log(Object.assign([1, 2, 3], [4, 5])) // 合并完還是數組 [4, 5, 3]
console.log(Object.assign({0:1,3:3}, [4, 5])) // 合并完是對象 {0: 4, 1: 5, 3: 3}
console.log(Object.assign( [4, 5],{0:1,3:3})) // 合并完還是數組 [1, 5, empty, 3] empty?// 3.對取值函數處理和賦值函數處理
var obj1={get foo(){return "a"}},
obj2={foo:()=>{return "a"}}
console.log(obj1) // foo: "a",obj1.foo得到的是函數執行結果,計算屬性原理?
console.log(obj2) // foo: ? foo(),obj2.foo得到的是函數地址
console.log(Object.assign({},{get obj1(){return "a"}},{obj2:()=>{return "a"}})) // {obj1: "a",obj2: ? obj2()}
用途
- 為對象添加屬性,方法
- 克隆對象,結合新語法合并多個對象
- 為屬性指定默認值
// 1.為對象同時添加(更新)多個屬性、方法
var obj = {title:"標題",dateStamp:"2020/5/22"},
newProp = {get dateStamp(){ return Date.now()},text:"新屬性",fun1(){return "新方法"}};
console.log(Object.assign(obj, newProp)) // {title: "標題", dateStamp: 1590119249783, text: "新屬性", fun1: ?}// 2.克隆
var obj = {};
var obj1 = { a: 1 };
Object.defineProperty(obj1, "k", {enumerable: true,// value: "hello",get() {console.log("獲取obj1的k值");} // 當使用了getter或setter方法,不允許使用writable和value這兩個屬性? });
console.log(Object.assign(obj, obj1)); // 獲取obj1的k值 {a: 1, k: undefined}
console.log(Object.assign(obj, obj1).k); // 獲取obj1的k值 undefined
console.log(obj1.k); // 獲取obj1的k值 undefined
// 采用這種方法克隆,只能克隆原始對象自身的值,不能克隆它繼承的值(什么意思?)// 3.為對象指定默認值和屬性
const defaultVal = {title: "未定義",time: "0"};
var obj = {},
obj1 = {};
Object.defineProperty(obj1, "title", {enumerable: true,// value: "hello",get() {console.log("獲取obj的title值");return "標題"}
});
// 注意順序,先默認值,再配置屬性,obj在最后
console.log(Object.assign({}, defaultVal,obj1,obj));
2.定義對象 - Object.defineProperty(obj, prop, descriptor)
定義屬性:Object.defineProperty(obj, prop, descriptor)
屬性在創建對象時就定義好了,所有特性的默認值都為true;而當使用defineProperty添加的屬性,特性的默認值都為false。當使用了getter或setter方法,不允許使用writable和value這兩個屬性?
obj ,待修改的對象
prop ,帶修改的屬性名稱
descriptor ,待修改屬性的相關描述
configurable ,屬性是否可配置。可配置的含義包括:是否可以刪除屬性( delete ),是否可以修改屬性的 writable 、 enumerable 、 configurable 屬性。 改為false之后,不能刪除修改(不可逆)。默認true
enumerable ,屬性是否可枚舉。可枚舉的含義包括:是否可以通過 for…in 遍歷到,是否可以通過 Object.keys() 方法獲取屬性名稱,是改為false,for in時不會被遍歷,但使用 "."依然可訪問。默認true
writable ,是否為可寫,改為false,當前屬性變為只讀。。默認true
value ,屬性的默認值。
set ,屬性的重寫器(暫且這么叫)。一旦屬性被重新賦值,此方法被自動調用。
get ,屬性的讀取器(暫且這么叫)。一旦屬性被訪問讀取,此方法被自動調用。
3.新數據類型- Symbol
Symbol是由ES6規范引入的一項新特性,它的功能類似于一種標識唯一性的ID。
定義
let s1 = Symbol();let s2 = Symbol("another symbol"); // 傳入描述信息 可以是任何可以被轉型成字符串的值,如:字符串、數字、對象、數組等let s3 = Symbol();console.log(s1,s2,s3)console.log(typeof s1); // 'symbol'console.log(s1===s2,s1===s3); // false - 每個Symbol實例都是唯一的。
應用
- 由于Symbol類型的key是不能通過Object.keys()或者for…in來枚舉的,它未被包含在對象自身的屬性名集合(property names)之中,所以可以把一些不需要對外操作和訪問的屬性使用Symbol來定義,作為對象的鍵(唯一);
- 因為這個特性,當使用JSON.stringify()將對象轉換成JSON字符串的時候,Symbol屬性也會被排除在外
- 定義常量不用再去想值的內容了
- 安全性高
- 多模塊共享唯一
const NAME = Symbol("it`s const key");const AGE = Symbol("it`s const key");let obj = {[NAME]: "默認名稱"};obj[AGE] = "賦值年齡";// 訪問console.log(obj[NAME],obj[AGE]) // 默認名稱, 賦值年齡// 獲取所有1console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]// 獲取所有2console.log(Reflect.ownKeys(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]// 定義常量不用再去想值的內容了const id = Symbol(); // id - 唯一// 注冊全局Symbol,實現多模塊共享唯一Symbollet s1 = Symbol.for("global_symbol_1"); //注冊一個全局Symbollet s2 = Symbol.for("global_symbol_1"); //獲取全局Symbol,注意描述一直才行let s3 = Symbol.for("global_symbol_3");console.log(s1 === s2); // trueconsole.log(s1 === s3); // false
未完待續…