3. 对象
3.1 创建对象
- 对象直接量
{}
-
属性名:JavaScript标识符、字符串(包括空字符串)
-
es6扩展
-
属性初始值简写:属性名与本地变量名同名时,可只写属性名。
-
对象方法简写:省略冒号和function关键字。
-
可计算属性名:使用[]表示该属性名称是可计算的。
-
- new + 构造函数
new Object()
new Array()
new Date()
new RegExp()
- Object.create(proto, [descriptors]) 以第一个参数为原型,创建新对象
-
proto,新创建对象的原型
-
可为null,此时会创建一个没有原型的对象,不继承任何东西,也没有基础方法。
-
创建普通空对象:
-
{}
-
new Object()
-
Object.create(Object.prototype)
-
-
-
第2个参数,属性描述
- 等同于调用
Object.defineProperties()
- 等同于调用
//对象直接量{ function createPerson(name, age){ let suffix = 'name' return { //属性简写 age, //对象方法简写 sayName(){ console.log(this.name) }, //可计算属性名,内容最终会被转化为字符串 ['full' + suffix]: name } }}//Object.create(proto, descriptors){ //以o为原型创建对象b,创建并描述y属性。 let o = { x: 1}; let b = Object.create(o, { y: { value: 2, writable: true, enumerable: true, configurable: true} });}复制代码
3.2 查询和设置属性
-
属性沿原型链查询,直到找到属性或查到原型为null为止。
-
给对象创建属性,或给属性赋值,不会修改原型链上的属性。
-
不能给只读属性重新赋值。
-
不能通过同名自有属性覆盖只读的继承属性。
let o = {}Object.defineProperty(o, 'x', { value: 1, writable: false});o.x = 2; //赋值失败,不能给只读属性重新赋值console.log(o.x); //1let b = Object.create(o);b.x = 2; //赋值失败,不能通过同名自有属性覆盖只读的继承属性console.log(b.x); //1Object.defineProperty(b, 'x', { value: 5});console.log(b.x); //5console.log(o.x); //1 给对象属性赋值,不会修改原型链上的属性复制代码
3.3 删除属性
delete
运算符可以删除对象属性。
-
但只是断开属性和属性值的联系,不会去操作属性值。
-
delete 只能删除自由属性,不能删除继承属性。
//只是断开属性和属性值的联系{ let obj = { key: { x: 1}}; let obj2 = obj.key; delete obj.key; console.log(obj); //{} console.log(obj2); // {x:1}}//delete 只能删除自由属性,不能删除继承属性。{ let o = Object.create({ x:1}); delete o.x; console.log(o.x); //1}复制代码
3.4 检测属性
-
in
自有属性 + 继承属性 -
hasOwnProperty()
自有属性 -
propertyIsEnumerable()
自有 && 可枚举属性
let o = { x: 1}let b = Object.create(o, { y: { value: 2, enumerable: false}});//in 检测自由属性+继承属性{ 'x' in b; //true 继承属性 'y' in b; //true 自有属性}//hasOwnProperty 检测自有属性{ b.hasOwnProperty('x'); //false 继承属性 b.hasOwnProperty('y'); //true 自有属性}//propertyIsEnumerable 检测自有&可枚举属性{ b.propertyIsEnumerable('x'); //false 继承属性 b.propertyIsEnumerable('y'); //false 自有、不可枚举属性 o.propertyIsEnumerable('x'); //true x是o的自由可枚举属性}复制代码
3.5 枚举属性
-
for/in
可枚举 && 自有属性 + 继承属性 -
Object.keys()
可枚举 && 自有属性 -
Object.getOwnPropertyNames()
自有属性
es6中自有属性的枚举顺序:
-
数字键按升序排序;
-
字符串键,按照被加入对象的顺序排序;
-
Symbol键按照他们被加入对象的顺序排序。
-
字符串键在数字键后。
let o = { x: 1, '1': 'judy'}let b = Object.create(o, { z: { value: 2, enumerable: false}});b[Symbol()] = 1;b['2'] = 'jack';b['0'] = 'alice';b.y = 3;//for/in 可枚举的自有+继承属性{ let keyList = [] for(let key in b){ keyList.push(key); } //先自有属性,后继承属性 console.log(keyList); // ['0', '2', y', '1','x']}//Object.keys() 可枚举的自有属性{ console.log(Object.keys(b)); //['0', '2', y']}//Object.getOwnPropertyNames() 自有属性,包括不可枚举的{ //字符串键在数字键后,字符串键按加入对象顺序排序 console.log(Object.getOwnPropertyNames(b)); //['0', '2', z', 'y']}复制代码
3.6 存取器属性(accessor property)
-
getter + setter, 可读写存取器属性
-
只有getter,只读存取器属性
-
只有setter,只写存取器属性
var p = { //x,y 可读写的数据属性 x: 2.0, y: 2.0, //r 可读写属性 get r(){ return Math.sqrt(this.x * this.x + this.y * this.y); }, set r(newVal){ var oldVal = Math.sqrt(this.x * this.x + this.y * this.y); var radio = newVal / oldVal; this.x *= radio; this.y *= radio; }, //theta 只读属性 get theta(){ return Math.atan2(this.x, this.y); }, //movement 只写属性 set movement(dis){ this.x += dis / this.theta; this.y += dis * this.theta; }};//r为可读写属性,可以读取和修改其值。console.log(p.r); //2.83p.r = 5;console.log(p.x, p.r); //5.36, 5//p为只读属性,改变其值,无效console.log(p.theta); //0.79p.theta = 1;console.log(p.theta); // //0.79//movement 为只写属性,读取值永远返回undefinedconsole.log(p.movement); //undefinedp.movement = 2;console.log(p.x); //6.08复制代码
Vue.js 计算属性的getter&setter
var app = new Vue({ el: '#app', data: { firstName: 'Machael', lastName: 'Jackson' }, computed: { fullName: { get: function(){ return this.firstName + this.lastName; }, set: function(newVal){ var names = newVal.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1] } } }})复制代码
3.7 属性的特性
-
属性描述符
-
数据属性:
value
,writable
,enumerable
,configurable
-
存取器属性:
get
,set
,enumerable
,configurable
-
-
Object.getOwnPropertyDescriptor()
获得对象某自有属性的属性描述符 -
Object.defineProperty()
、Object.defineProperties()
创建或修改属性-
不可扩展对象,可以编辑已有的自有属性,但不可增加新属性。
-
不可配置属性,不可以修改其
configurable
和enumerable
。 -
不可配置的数据属性,可以将其
writable
从true
改为false
,但不可以从false
改为true
。 -
数据属性的
configurable
和writable
同时为false
时,不能修改其值。有一个为true时,可以修改。 -
不可配置的存取器属性,不能修改其getter和setter,也不能将其转为数据属性。
-
不可配置的数据属性,不能将其转为存取器属性。
-
let o = { x: 1, get y(){}, set y(newV){}};//数据属性{ Object.getOwnPropertyDescriptor(o, 'x'); //{value: 1, writable: true, enumerable: true, configurable: true}}//存取器属性{ Object.getOwnPropertyDescriptor(o, 'y'); //{get: f, set: f, enumerable: true, configurable: true}}//Object.defineProperty(){ // 将数据属性,转为访问器属性 Object.defineProperty(o, 'x', { get: function(){ return 2}}); Object.getOwnPropertyDescriptor(o, 'x'); //get: ƒ, set: undefined, enumerable: true, configurable: true}}//Object.defineProperties(){ Object.defineProperties(o, { x: { configurable: true}, y: { value: 2} }); Object.getOwnPropertyDescriptor(o, 'y'); //{value: 2, writable: false, enumerable: true, configurable: true}}复制代码
属性特性的默认值:
//通过Object.defineProperty()给对象新建属性,3个特性值默认为false{ Object.defineProperty(o, 'x', { value: 1}); Object.getOwnPropertyDescriptor(o, 'x'); //{value: 1, writable: false, enumerable: false, configurable: false}}//通过如下方式新建属性,3个特性值默认为true{ o.y = 1; Object.getOwnPropertyDescriptor(o, 'y'); //{value: 1, writable: true, enumerable: true, configurable: true}}复制代码
3.8 对象的三个属性
-
原型属性
-
获取原型
Object.getPrototypeOf
-
检测原型
isPrototypeOf()
- object instanceof constructor
-
类属性:
Object.prototype.toString.call()
-
可扩展性
-
检测可扩展性:
-
Object.isExtensible()
可扩展 -
Object.isSealed()
封闭 -
Object.isFrozen()
冻结
-
-
将对象转为不可扩展:(不影响原型和继承)
-
Object.preventExtensions()
对象不可扩展 -
Object.seal()
对象不可扩展 && 自有属性不可配置 -
Object.freeze()
对象不可扩展 && 自有属性不可配置 && 自有属性只读(不影响setter)
-
//原型属性{ let o = { x: 1}; let b = Object.create(o); Object.getPrototypeOf(b); //{x: 1} o.isPrototypeOf(b); //true}//类属性{ let d = new Date(); Object.prototype.toString.call(d); // '[object Date]'}//可扩展性{ let o = { x: 1}; let b = Object.create(o); b.z = 1; Object.preventExtensions(b); Object.getOwnPropertyDescriptor(b, 'z'); //{value: 1, writable: true, enumerable: true, configurable: true} Object.seal(b) Object.getOwnPropertyDescriptor(b, 'z'); //{value: 1, writable: true, enumerable: true, configurable: false} Object.freeze(b); Object.getOwnPropertyDescriptor(b, 'z'); //{value: 1, writable: false, enumerable: true, configurable: false} b.y = 1; console.log(b.y); //undefined o.k = 1; console.log(b.k); //1 console.log(Object.isExtensible(b)); // false console.log(Object.isSealed(b)); // true console.log(Object.isFrozen(b)); // true console.log(Object.isExtensible(o)); //true}复制代码