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); //1
let b = Object.create(o);
b.x = 2; //赋值失败,不能通过同名自有属性覆盖只读的继承属性
console.log(b.x); //1
Object.defineProperty(b, 'x', {value: 5});
console.log(b.x); //5
console.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.83
p.r = 5;
console.log(p.x, p.r); //5.36, 5
//p为只读属性,改变其值,无效
console.log(p.theta); //0.79
p.theta = 1;
console.log(p.theta); // //0.79
//movement 为只写属性,读取值永远返回undefined
console.log(p.movement); //undefined
p.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
}