1.语法
对象的定义有两种形式:声明形式和构造形式
声明形式:
var myobj={key:value .....}
构造形式:
var myobj=new Object(); myobj.key=value;
2.对象类型
string、number、boolean、null、undefined、symbol、object。 (红色的是6中基本类型)
注意:null是基本类型,为什么typeof null===“object”呢?
答:不用的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话被判断为object类型,null的二进制表示全是0,自然前三位也是0,所以执行typeof时会返回“object”。
JavaScript中的内置对象:String、Number、Boolean、Object、Function、Array、Date、RegExp、Error。这些内置对象可以当做构造函数来用,从来构造一个对应类型的新对象。js在必要时会自动把字符串字面量转换成一个相应的对象。
3.对象的内容
存储在对象容器内部的是引用,指向内容值的真正的存储位置。
对内容的访问方式:属性访问和键访问
var myObject={
a:2;
};
myObject.a;//属性访问,要求属性名合法
myObject["a"];//可以接受任意utf-8/unicode字符串作为属性名
注意:属性名永远是字符串,如果不是字符串,则首先转化为字符串。
4.可计算属性(ES6)
例子:myobject[prefix + name].其最常用的场景是ES6中的symbol
5.复制对象
包括浅复制和深复制。
浅复制:只复制对象的引用,而不会复制其深层元素。
深复制:不仅仅复制对象的引用,还 将引用所引用到的对象全部都引用一遍,既将其深层元素也都因引用一遍。
浅复制的实现:
方式1:
function clone(obj){
var myObj={};
for(var i in myObj){
myObj[i]=obj[i];
}
return myObj;
}
方式2:利用ES6中的object.assign(目标对象,源对象1,源对象2.......)。源对象属性的一些特性(如writable)不会被复制到目标对象。
var obj={
a:1
}
var myObj=Object.assign({},obj);//浅复制
6.属性描述符
每当给对象创建一个属性的时候,它都会有一个默认的属性描述符。用来描述该属性的值,该属性可写(writable),该属性可枚举(enumerable),该属性可是设置(configurable)。
Object.defineProperty(...)我们也可以自己添加一个新属性或者修改已有的属性,并对它的特性进行设置。
var myObject={};
Object.defineProperty(myObject,"a",{
//给myObject对象添加一个属性a,然后给设置一些特性
value:2,
writable:true,
configurable:true,
enumerable:true
})
7.[[Get]]和[[Put]]
这两个属性是对象默认的。
属性在访问的时候,内部实现了[[Get]]操作。对象默认的内置[[Get]]操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。
属性在赋值的时候,会被触发[[Put]]操作。
如果已经存在这个属性,[[Put]]算法大致会检查下面的内容:
(1)属性是否是访问描述符?如果是并且存在setter就调用setter。
(2)属性的数据描述符中writable是否是false?如果是,在非严格模式下静默失败,在严格模式下抛出TypeError异常。
(3)如果都不是,将该值设置为属性的值
8.属性的存在性
判断地一个对象中是否含有某个属性:
in 操作符:会检查属性是否在对象及其[[Prototype]]链中。
hasOwnProperty(...):只会检查属性是否在当前对象中,不会检查[[Prototype]]链。
8.1枚举
如何区分属性是否可枚举: myObject.propertyIsEnumerable(属性名)
另外:Object.keys(...):会返回一个数组,包含所有可枚举属性;
Object.getOwnPropertyNames(...):返回一个数组,包含所有的属性,不论是否可枚举。
var myObject={};
Object.defineProperty(myObject,"a",{
//让a像普通属性一样可以枚举
enumrable:true,value:2
});
Object.defineProperty(myObject,"b",{
//让b不可枚举
enumrable:false,value:3
});
myObject.propertyIsEnumerable("a");//true
myObject.propertyIsEnumerable("b");//false
Object.keys(myObject);//["a"]
Object.getOwnPropertyNames(myObject);//["a","b"]
9.如何遍历对象
方式1:for...in...
方式2:for...of...(前提:对象本身定义了迭代器)
遍历一个对象的属性:Object.keys();返回对象的属性字符串数组。
function Person() {
}
Person.prototype.name="Nick";
Person.prototype.age=22;
Person.prototype.sayName=function () {
alert(this.name);
};
var keys=Object.keys(Person.prototype);
console.log(keys);//["name","age","sayName"]
keys中保存一个数组,数组中是“name”,“age”,“sayName”,这个顺序也是它们在for-in循环中出现的顺序。
如何遍历一个对象: for...in...
var obj={
a:'ss',
b:'bb',
c:"cc",
}
for(let key in obj){
console.log(key,obj[key]);
}
结果:
当对象为空的时候该怎么办:
var obj={
a:'ss',
b:'bb',
c:"cc",
}
delete obj.a;//直接删除a属性
delete obj.b;//直接删除b属性
console.log(obj,Object.keys(obj));//{c:"cc"} ["c"]
delete obj.c;
console.log(obj,Object.keys(obj));//{ }[]
Object.keys()遍历返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。所以我们可以使用数组api了
var obj={
a:'ss',
b:'bb',
c:"cc",
}
Object.keys(obj).forEach(function(value,index){
console.log(value,index)
})
结果: