福州中小企业网站制作,祥云平台 网站建设,重庆深蓝科技网站开发,锦州网站建设市场ECMA-262将对象定义为一组属性的无序集合。
1 内部属性描述
1.1 数据属性
[[Configurable]]#xff1a;可配置性#xff0c;直接定义在对象的属性该特性默认为true#xff0c;表示可以对属性进行删除、修改等操作。[[Enumerable]]#xff1a;可枚举性#xff0c;直接定…ECMA-262将对象定义为一组属性的无序集合。
1 内部属性描述
1.1 数据属性
[[Configurable]]可配置性直接定义在对象的属性该特性默认为true表示可以对属性进行删除、修改等操作。[[Enumerable]]可枚举性直接定义在对象的属性该特性默认为true它决定了我们是否可以通过for-in循环遍历对象的属性。[[Writable]]可写性直接定义在对象的属性该特性默认为true表示属性的值是否可以被修改。[[Value]]属性的实际数据值默认为undefined。
我们可以使用Object.defineProperty来定义数据属性。
let student1 { name: student1 };
Object.defineProperty(student1, sex, {configurable: false,enumerable: false,writable: false,value: male,
});
//测试可配置性
delete student1.sex;
console.log(student1.sex);
console.log();
//测试可枚举性
for (const key in student1) {console.log(key );
}
console.log();
//测试可写性
student1.sex female;
console.log(student1.sex);输出
malenamemale除了属性configurable属性为false的情况我们可以多次调用defineProperty。
如果调用了defineProperty但不指定configurable、enumerable、writable的值则它们默认被设为false。
1.2 访问器属性
[[Configurable]]表示属性是否可修改。直接定义在对象的属性该特性默认为true。[[Enumberable]]表示属性是否可枚举。直接定义在对象的属性该特性默认为true。[[Get]]获取属性时调用的函数。默认为undefined。[[Set]]设置属性时调用的函数。默认为undefined。
同样我们使用Object.defineProperty来定义访问器属性。
let person {firstName: John,lastName: Doe,
};
Object.defineProperty(person, fullName, {get() {return this.firstName this.lastName;},set(value) {const parts value.split( );this.firstName parts[0];this.lastName parts[1];}
});
console.log(person.fullName);
person.fullName Jane Smith;
console.log(person.firstName);
console.log(person.lastName);输出
John Doe
Jane
Smith访问器属性和数据属性的不同之处在于
数据属性关注于数据的值与可写性访问器属性关注获取和设置数据时进行的操作。
2 定义多个属性
可以使用Object.defineProperties一次性定义多个属性。
let person{};
Object.defineProperties(person,{name:{value: Jane},age:{get(){return this.age;},set(value){this.agevalue;}}
});3 读取属性特性
使用Object.getOwnPropertyDescriptor读取属性的属性描述符。
使用上面一节中定义好的person对象。
let descriptor1Object.getOwnPropertyDescriptor(person,name);
console.log(descriptor1.configurabledescriptor1.configurable);
console.log(descriptor1.enumerabledescriptor1.enumerable);
console.log(descriptor1.writabledescriptor1.writable);
console.log(descriptor1.valuedescriptor1.value);
let descriptor2Object.getOwnPropertyDescriptor(person,age);
console.log(descriptor2.configurabledescriptor2.configurable);
console.log(descriptor2.enumerabledescriptor2.enumerable);
console.log(descriptor2.getdescriptor2.get);
console.log(descriptor2.setdescriptor2.set);运行结果
descriptor1.configurablefalse
descriptor1.enumerablefalse
descriptor1.writablefalse
descriptor1.valueJane
descriptor2.configurablefalse
descriptor2.enumerablefalse
descriptor2.getget() {return this.age;}
descriptor2.setset(value) {this.age value;}注意到没有设置的configurable、enumerable、writable都被设置为false。
4 合并对象
合并对象即将一个对象的属性复制到目标对象上这也被称为混入mixin。学过Vue的知道Vue里面也有个混入的概念Vue2 混入。
ES6提供Object.assign()方法来合并对象。
该方法将一个或多个源对象的可枚举和自有属性复制到目标对象上。
可枚举判断Object.propertyIsEnumerable()。自有属性判断Object.hasOwnProperty()。
复制的具体操作是调用源对象的get获取属性再调用目标对象的set属性。
const target {_a:,// set a(val) {// console.log(调用target属性a的set);// this._a val;// }
};
Object.defineProperty(target, a, {set(val) {console.log(调用target属性a的set);this._a val;},
});
const source1 {// get a() {// console.log(调用source1属性a的get);// return a;// }
};
Object.defineProperty(source1, a, {get() {console.log(调用source1属性a的get);return a;},enumerable: true
});
const source2 { b: b };
Object.assign(target, source1, source2);
console.log(target);在字面中定义的属性的未设置的数据属性和访问器属性都为默认值而在Object.defineProperty中定义的属性的未设置的特性要么为false要么为undefined。
上面我们给source1的访问器属性a设置enumerable: true就是这个原因不然无法复制a属性。
运行结果
调用source1属性a的get
调用target属性a的set
{ _a: a, b: b }Object.assign还有以下注意的地方 同名的属性后面的会覆盖前面的。 Object.assign是浅复制即只复制对象内部元素的引用。 const originalObject{a:1}
const anotherShallowCopy Object.assign({}, originalObject);
console.log(anotherShallowCopy originalObject);//false
console.log(anotherShallowCopy.a originalObject.a);//true在复制过程出现错误Object.assign不会回滚到初始状态。
5 严格相等判断
大多数情况我们可以使用来判断严格相等但以下的特殊边界情况却不尽人意
console.log(0 -0); //true
console.log(0 0); //true
console.log(-0 0); //true
console.log(NaN NaN); //false其中NaN表示Not a Number可以使用全局函数isNaN检查。
ES6提供了Object.is来应对上述所有情况。
Object.is(v1,v2);使用递归Object.is剩余参数比较多个值的相等性
function areValuesEqual(a,...values){return Object.is(a,values[0])(values.length2||areValuesEqual(...values));
}或者使用every
function areValuesEqual(a, ...values) {return values.every(value Object.is(a, value));
}6 增强的对象语法
6.1 属性值的简写
const name John;
const age 30;// 使用属性值简写创建对象
const person {name,age,sayHello() {console.log(Hello, my name is ${this.name}.);}
};console.log(person); // 输出 { name: John, age: 30 }
person.sayHello(); // 输出 Hello, my name is John.6.2 可计算属性
可计算属性允许你在定义对象时在方括号内使用表达式来定义对象名。
const methodSuffix Hello;const dynamicObject {[say methodSuffix]() {console.log(Hello, World!);}
};dynamicObject.sayHello(); // 输出 Hello, World!6.3 简写属性名
let keyAge;
let person{_name: Jane,_age: 18,get name(){return this._name;},set name(val){this._nameval;},sayHello() {console.log(Hello, my name is ${this._name}.);},[saykey](){console.log(Hello, my age is ${this._age}.);}
};7 对象解构
对象解构指可以使用与对象匹配的结构来实现对象属性赋值。
let person{name: Jane,age: 18
};
//别名
let {name:personName,age:personAge}person;
//属性简写
let {name,age}person;
//没有匹配的属性被赋值为undefined
let {name,age,height}person;
//解构时赋值
let {name,age,height180}person;解构的本质是使用ToObject函数将元数据转为对象。
因此null和undefined不能被解构。
如果给事先声明好的变量赋值则解构表达式整个需要包裹在一对括号里。
1嵌套解构
let {outer:{inter}}obj;2部分解构
解构像我们的对象合并一样是尽力而为的行为一旦解构过程发生错误过程终止且无法回滚也就是只解构了部分。
3对象解构为函数参数
function sum([a, b]) {return a b;
}const numbers [3, 5];console.log(sum(numbers)); // 输出 8