ES6 对象的扩展
2019-06-25 本文已影响0人
gitblong
function f(x, y) {
return {x, y};
}
let f1 = f(1, 2);
console.log(f1);
//属性的可枚举性和遍历
let obj = {foo: 123};
let ownPropertyDescriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
console.log(ownPropertyDescriptor);
/*{ value: 123,
writable: true,
enumerable: true,
configurable: true }
如果enumerable为false,就标识某些操作会忽略当前属性
目前,有四个操作会忽略enumeration为false的属性
for...in循环 只遍历对象自身的和继承的可枚举的属性,
Object.keys() 返回对象自身的所有可枚举的属性的键名
JSON.stringify() 只串行化对象自身的可枚举的属性
Object.assign() 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性
由于for...in会返回继承的属性,其它三个方法都会忽略继承的属性,只处理对象自身的属性
所以enumerable属性实质是为了限制for...in遍历继承的属性而定义的
*/
let enumerable = Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable;
//false
let enumerable1 = Object.getOwnPropertyDescriptor([], 'length').enumerable;
//false
console.log(enumerable, enumerable1);
//super关键字
const proto = {
foo1: 'hello'
};
const objSuper = {
foo: 'world',
[Symbol()]: 1,
isEnumerable: false,
find() {
return super.foo1;
}
};
Object.setPrototypeOf(objSuper, proto);
let find = objSuper.find();//hello
console.log(find);
//遍历Keys的5种方法
//1
let pArr = [];
for (p in objSuper) {
pArr.push(p)
}
console.log(pArr); //for遍历父级属性
Object.defineProperty(objSuper, 'isEnumerable', {
enumerable: true,
});
console.log(objSuper);
//2
console.log(Object.keys(objSuper)); //只遍历本身可枚举属性
//3
console.log(Object.getOwnPropertyNames(objSuper)); //只遍历本身所有属性
//4
console.log(Object.getOwnPropertySymbols(objSuper));//只遍历Symbols属性
//5
console.log(Reflect.ownKeys(objSuper)); //遍历所有属性
/*遍历属性的次序规则
* (1)首先遍历所有数值键,按照数值升序排列
* (2)其次遍历所有字符串键,按照加入时间升序排列
* (3)最后遍历所有Symbol键,按照加入时间升序排列
*
* */
/*
[ 'foo', 'find' ]
[ 'foo', 'find' ]
[ Symbol() ]
[ 'foo', 'find', Symbol() ]
*/
let propertyKeys = Reflect.ownKeys({[Symbol()]: 0, b: 0, 10: 0, 2: 0, a: 0});//[ '2', '10', 'b', 'a', Symbol() ]
console.log(propertyKeys);
//扩展运算符 ... rest参数...param
//1.解构赋值
let {x, y, ...z} = {x: 1, y: 2, a: 3, b: 4};//x = 1, y= 2, z={a:3,b:4}
console.log(x, y, z);
try {
let {...zz1} = null; //运行时错误
let {...zz2} = undefined; //运行时错误
} catch (e) {
console.log("运行时错误");
}
let someObject = {};
let {x2, y2, ...z2} = someObject; //undefined undefined {}
console.log(x2, y2, z2);
//结构赋值必须是最后一个参数,否则会报错
try {
// let {...x3, y3, z3} = someObject; //句法错误
// let {x4, ...y4, ...z4} = someObject; //句法错误
} catch (e) {
console.log("句法错误")
}
//结构赋值是浅拷贝,即如果一个值是复合类型的值(数组、对象、函数)、那么结构赋值拷贝的是这个值得引用,而不是这个值得副本。
let objLightCopy = {a: {b: 1}};
let {...xCopy} = objLightCopy;
objLightCopy.a.b = 2;
console.log(xCopy, xCopy.a.b);//{ a: { b: 2 } } 2
//扩展运算符的结构赋值,不能复制继承自原型对象的属性
let o1 = {a: 1};
let o2 = {b: 2};
o2.__proto__ = o1;
let {...o3} = o2;
console.log(o3);// { b: 2 }
console.log(o3.a);// undefined
let oCreate = Object.create({x: 1, y: 2});
oCreate.z = 3;
console.log(oCreate.__proto__, oCreate);//{ x: 1, y: 2 } { z: 3 }
let {xCreate, ...newObject} = oCreate;
let {yCreate, zCreate} = newObject;
console.log(xCreate, yCreate, zCreate);//1 undefined 3
//扩展运算符
let zzz = {a: 3, b: 4};
let n = {...zzz};
console.log(n);//{a:3,b:4}
let stringsArr = ['a', 'b', 'c'];
let stringObject = {e: 1, f: 2, g: 3};
let foo = {...stringsArr};
let fooObject = {...stringObject};
stringsArr[0] = 'd';
stringObject.e = 4;
//[ 'd', 'b', 'c' ] { e: 4, f: 2, g: 3 } { '0': 'a', '1': 'b', '2': 'c' } { e: 1, f: 2, g: 3 }
console.log(stringsArr, stringObject, foo, fooObject,);
let stringHelloObject = {...'hello'};
let stringHelloArr = [...'hello'];
console.log(stringHelloObject, stringHelloArr);//{ '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' } [ 'h', 'e', 'l', 'l', 'o' ]
//完整克隆一个对象的三种方法
//方法1
let clone1 = {
__proto__: Object.getPrototypeOf(stringHelloObject),
...stringHelloObject
};
//写法2
let clone2 = Object.assign(
Object.create(Object.getPrototypeOf(stringHelloObject)),
stringHelloObject
);
//写法3
let clone3 = Object.create(Object.getPrototypeOf(stringHelloObject), Object.getOwnPropertyDescriptors(stringHelloObject));
stringHelloObject[0] = 'god';
console.log(clone1, clone1.__proto__, clone1.prototype);//{ '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' } {} undefined
console.log(clone2, stringHelloObject);//{ '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' } { '0': 'god', '1': 'e', '2': 'l', '3': 'l', '4': 'o' }
console.log(clone3, Object.getPrototypeOf(stringHelloObject), Object.getOwnPropertyDescriptors(stringHelloObject));
/*
*
* { '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' } {} { '0':
{ value: 'god',
writable: true,
enumerable: true,
configurable: true },
'1':
{ value: 'e',
writable: true,
enumerable: true,
configurable: true },
'2':
{ value: 'l',
writable: true,
enumerable: true,
configurable: true },
'3':
{ value: 'l',
writable: true,
enumerable: true,
configurable: true },
'4':
{ value: 'o',
writable: true,
enumerable: true,
configurable: true } }
*
* */
//合并对象
let andA = {a: 1}
let andB = {b: 2}
let ab = {...andA, ...andB};
let abAssign = Object.assign({}, andA, andB);
console.log(ab == abAssign ,ab, abAssign);//false { a: 1, b: 2 } { a: 1, b: 2 }
//__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
// __proto__属性用于读取或设置当前对象的prototype对象,目前所有浏览器都部署了这个对象