对象可以通过两种形式表示
1.声明文字形式
var myObj={
key:value
}
2.构造形式
var myObj=new Object();
myObj.key=value;
类型
简单基本类型string,boolean,number, null,undefined
内置对象 String,Number,Boolean,Object,Function,Array,Date,RegExp,Error
var str='i am a string';
console.log(typeof str); // string
console.log(str instanceof String); //false
var str=new String('i am a string');
console.log(typeof str); //object
console.log(str instanceof String); //true
'i am a string’并不是一个对象,只是一个字面量,并且是一个不可变的值。如果要在上面操作,需要将其转变为String对象
复制对象
function anotherFunction(){
}
var anotherObject={
c:true
}
var anotherArray=[]
var myObject={
a:2,
b:anotherObject,
c:anotherArrya,
d:anotherFunction
}
anotherArray.push(anotherObject,myObject)
浅拷贝:
复制出的新对象中a的值会复制旧对象中a的值,也就是2,但是新对象中b,c,d三个属性其实只是三个引用,它们和就对象中b,c,d引用的对象是一样的
Object.assign(…)方法的第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个
var newObj=Object.assign({},myObject);
console.log(newObj.a); // 2
console.log(newObj.b==anotherObject); // true
console.log(newObj.c==anotherArray); // true
console.log(newObj.d==anotherFunction); // true
深复制:
除了复制myObject以外,还会复制anotherObject和anotherArray。这时候问题来了,anotherArray引用了anotherObject和myObject,所以又需要复制myObject,这样由于循环引用导致死循环
对象的属性描述符
var myObject={
a:2,
}
console.log(Object.getOwnPropertyDescriptor(myObject,'a'));
//{ value: 2, writable: true, enumerable: true, configurable: true }
Object.defineProperty(…)添加一个新属性或者修改一个已有属性
总共包含四个特性:数据值,writable,enumerable,configurable
writable决定是否可以修改属性的值
var myObject={
}
Object.defineProperty(myObject,"a",{
value:2,
writable:false, //不可写
configurable:true,
enumerable:true
})
myObject.a=3
console.log(myObject.a) // 2
configurable只要属性是可配置的,就可以使用defineProperty(…)方法修改属性描述符
configurable修改成false是单向操作,无法撤销,除了writable,其他属性不可以修改。delete属性也会失败
var myObject={
}
Object.defineProperty(myObject,"a",{
value:2,
writable:true,
configurable:false,
enumerable:true
})
myObject.a=3
console.log(myObject.a) // 3
Object.defineProperty(myObject,"a",{
value:4,
writable:true,
configurable:true,//configurable修改成false是单向操作,无法撤销,除了writable,其他属性不可以修改
enumerable:true
})
delete myObject.a
//TypeError: Cannot redefine property: a
Enumerable属性是否会出现在对象的属性枚举中,如果把enumerable:false,这个属性不会出现在for…in循环中
var myObject={
}
Object.defineProperty(myObject,"a",{
value:2,
writable:true,
configurable:false,
enumerable:false
})
myObject.b=3
for (var k in myObject){
console.log(k,myObject[k])
}
// enumerable:false.结果为:b 3
// enumerable:true.结果为:
//a 2
//b 3
对象的访问描述符
对象定义了getter和setter,对于访问描述符来说,js会忽略它们的value和writable特性,关心的是get和set,还有configurable和enumerable特性
var myObject={
get a(){
return this._a_;
},
set a(val){
this._a_=val*2;
}
}
myObject.a=3
Object.defineProperty(myObject,'b',{
get:function(){
return this.a*2
},
// 确保b会出现在对象的属性列表中
enumerable:true,
configurable:true
})
console.log(myObject.a) // 6
console.log(myObject.b) // 12
对象属性是否存在
in操作符会检查属性是否在对象及其原型链中
hasOwnProperty只会检查属性是否在对象中,不会检查原型链
var myObject={
a:2
}
console.log("a" in myObject); // true
console.log("b" in myObject); // false
console.log(myObject.hasOwnProperty("a")); // true
console.log(myObject.hasOwnProperty("b")); // false
枚举
myObject.b确实存在并且有访问值,但是却不会出现在for…in循环中,因为enumerable:false
myObject.propertyIsEnumerable(“b”)会检查给定的属性名是否直接存在于对象中(而不是在原型链上)并且满足enumerable:true
Object.keys(…)会返回一个数组,包含所有可枚举属性。
Object.getOwnPropertyNames(…)会返回一个数组,包含所有属性,无论是否可枚举
var myObject={};
Object.defineProperty(myObject,"a",{enumerable:true,value:2});
Object.defineProperty(myObject,"b",{enumerable:false,value:3});
console.log(myObject.b); // 3
console.log("b" in myObject); //true
console.log(myObject.hasOwnProperty("b")); //true
console.log(myObject.propertyIsEnumerable("a")); //true
console.log(myObject.propertyIsEnumerable("b")); //false
console.log(Object.keys(myObject));
console.log(Object.getOwnPropertyNames(myObject));
for(var k in myObject){
console.log(k,myObject[k]) // a 2
}