文章目录
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]) // 默认名称, 赋值年龄
// 获取所有1
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]
// 获取所有2
console.log(Reflect.ownKeys(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]
// 定义常量不用再去想值的内容了
const id = Symbol(); // id - 唯一
// 注册全局Symbol,实现多模块共享唯一Symbol
let s1 = Symbol.for("global_symbol_1"); //注册一个全局Symbol
let s2 = Symbol.for("global_symbol_1"); //获取全局Symbol,注意描述一直才行
let s3 = Symbol.for("global_symbol_3");
console.log(s1 === s2); // true
console.log(s1 === s3); // false
未完待续…