对象是JS的基本数据类型,对象是一种复合值,它将很多值聚合在一起,可以通过它们的键值(属性名)来访问他们的这些属性值
对象的创建
- var obj=new Object();
- var obj={};
- var obj=Object.create(Object.prototype) //es5中的方法
var a={
tee:"asd",
glass:"aaaa",
clockIn:function () {
alert("AM 9:30")
},
clockOut:function () {
alert("PM 9:30")
}
};
另外可以定义新属性:
a.pants="asdfa";
a['kaddd']="asdff";
这两种都可以输出是一样的,第一个是新增了一个属性名为pants,属性值为asdfa的属性,第二个是新增了一个属性名为kaddd,属性值为asdff的属性;
还有是在es5中有两个方法,十分重要,用于对 对象 其中的属性进行定义或者修改,一个是Object.defineProperty(),另一个是Object.defineProperties(),另外在es5中增加了属性描述符,通过属性描述符可以更加细腻的控制属性的不同操作,属性描述符分为两种类型:数据描述符和存取描述符;
数据描述符:是一个可写或者不可写值的属性。
存取描述符:是由一对getter和setter函数功能来描述属性。
描述符必须是两者之一,但是不能共存。(https://blog.csdn.net/qq_17335153/article/details/52584727)
属性描述符 | 数据描述符 | 存取描述符 | 描述 |
configurable | Yes | Yes | 当且仅当configurable为true时,属性描述符才可以被修改(属性描述符的修改 得使用defineProperty()和defineProperties()方法),另外该属性也可以从对象上 被删除,默认值为false |
enumerable | Yes | Yes | 当且仅当enumerable为true时,该属性才可以被枚举(枚举属性代表可以被for...in查询到 查不到的代表不具备枚举属性),默认为false |
value | Yes | No | value该属性对应的值,默认为undefined |
writable | Yes | No | 当且仅当writable为true时,value才可以被赋值运算符改变,默认为false |
get | No | Yes | 给属性提供get方法,如果没有getter则为undefined,该方法返回值被用作属性值(这个 理解成是为了获取返回值)默认为undefined |
set | No | Yes | 给属性提供setter方法,如果没有setter则为undefined,该方法将接受唯一参数,并 将该参数的新值分配给该属性(这个是为了设置属性,并不需要返 回值),默认为undefined |
Object.defineProperty(obj,prop,descriptor):这个方法的主要功能是对 对象的属性和属性值进行定义和修改,但这个方法添加的只能是一个属性和属性值
obj:目标对象,要对这个对象新增或修改属性
prop:要新增或者修改属性的名字
descriptor:属性描述符
,举个例子:
Object.defineProperty(a,"name",{
set:function (value) {
switch (value){
case 'nike':
alert("nike");
break;
case "ven":
alert("ven");
break;
default:
alert("这个比较奇葩")
break;
}
}
})
解释:给a这个对象,添加或修改属性名为name的属性值,具体修改后的属性值为function里的方法计算出来的
Object.defineProperties(obj,descriptor)
defineProperties是defineProperty的复数,显然可见是可以给对象进行多个属性的添加和修改
obj:目标对象,要对这个对象做一些操作
descriptor:属性描述符
var xm={} Object.defineProperties(xm,{ "glass":{ //属性名 value:"joy", //属性值 writable:true, //允许属性值“joy”被写入修改 configurable:false,//不允许delete xm.galss,不允许defineProperty()修改属性描述符 enumerable:false//不允许被for..in查询到 }, "arm":{ //属性名 configurable:true, //允许删除,允许使用defineProperty()修改属性描述符 enumerable:true, //允许被搜索到 set:function (value) { //给这个属性设置一个函数,注意,调用对象的函数的方法是xm.xarm(),有括号的,代表方法,不是xm.xarm,没有括号意思是打印值 return value; } }, "xarm":{ //属性名 configurable:false, enumerable:false, value:function () { //属性值,这边属性值是一个函数,注意,调用对象的函数的方法是xm.xarm(),有括号的,代表方法,不是xm.xarm,没有括号意思是打印值 alert(1); } } })
Object.create(prototype,descriptor)
创建一个具有指定原型,可选择性包含指定属性的对象,最终返回的是新创建的对象
prototype:指新创建对象的原型对象
descriptor:添加到新创建对象的属性
var pol=Object.create(Object.prototype,{ glass:{ //属性名 value:"joy", //属性值 writable:true, //可写入 configurable:false, //允许被defineProerty()修改,这个属性允许被delete删除,这个例子就是允许被delete pol.glass enumerable:false //允许被for...in搜索到 } }) console.log(pol)
属性的访问
var a={
name:"toy",
sex:"男",
asd:function(a){}
}
a.name; //访问name属性,输出toy
a.asd(a); //访问asd方法,并传参数a
a['name'] //访问name属性,输出toy
a['asd'] //?这个还要查一查
属性的设置
var pokx={ xaaa:"asd" }; Object.defineProperties(pokx,{ name:{ //属性名 value:"joy", //属性值 configurable:true, //可删除可修改属性描述符 writable:false //可写入修改 } }) console.log(pokx)
pokx.xaaa; //输出asd
pokx.xaaa="qwe"; //输出qwe,可修改
pokx.name; //输出joy
pokx.name="ree"; //输出ree,因为writable为false,不允许写入
属性的删除
var pokx={ xaaa:"asd" }; Object.defineProperties(pokx,{ name:{ //属性名 value:"joy", //属性值 configurable:false, //可删除可修改属性描述符 writable:false //可写入修改 } }) console.log(pokx)
delete pokx.xaaa; //输出true,删除成功
delete pokx.name; //输出false,删除失败,因为修改新定义的属性name的configurable设置成了false,不允许修改或删除
属性的检测
- for...in:运算符,通过for...in检测对象上包括原型链上的所有具有枚举属性的对象
var obj={ xaaa:"asd" }; Object.defineProperties(obj,{ name:{ //属性名 value:"joy", //属性值 configurable:false, //可删除可修改属性描述符 writable:false, //可写入修改 enumerable:true }, galss:{ value:function (a) { return a }, enumerable:true }, shit:{ value:"ul", enumerable:false } }) Object.prototype.ola=function () { }; for (var a in obj){ console.log(a); //这里输出把整个对象上添加的ola也输出了 }
- hasOwnProperty():检测对象上的自由属性,如果是自有属性,则返回true,如果没有则返回false
for (var a in obj){ if(obj.hasOwnProperty(a)==true){ //也可以直接判断obj.hasOwnProperty(a) console.log(a); //这里输出就不会出出ola属性了 } }
- propertyIsEnumerable():检测自有且可枚举的属性,是hasOwnProperty()方法的进一步加强
枚举属性
- for...in,下例中用for..in显示了所有的枚举属性,如果enumerable设置了false,那么属性就不会被for...in到
- Object.key(obj):是es5中的一个方法,只会将对象自有的属性名以数组的形式返回,这个方法就不必担心有没有原型链上的对象,示例如下
var obj={ xaaa:"asd" }; Object.defineProperties(obj,{ name:{ //属性名 value:"joy", //属性值 configurable:false, //可删除可修改属性描述符 writable:false, //可写入修改 enumerable:true }, galss:{ value:function (a) { return a }, enumerable:true }, shit:{ value:"ul", enumerable:false } }) Object.prototype.ola=function () { }; var aox=Object.keys(obj); console.log(aox);
这边最终会输出:[‘xaaa’,‘name’,‘galss’],其中shit因为enumerable设置了false,无法被枚举,而整个对象上的ola则不是obj的自有属性。
属性复制
Object.assign(terget,...sources)
terget:目标对象
...sources:一个或多个的源对象
- 将所有 可枚举的属性的值 从 一个或多个源对象 上 复制 到 目标对象,然后将返回新生成的目标对象
- 如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖,后来的源的属性将类似的覆盖早先的属性
var aa={ name:"joy", glass:"sk", shit:"shit" } var ab={ name:"pol", shit:"sk" } var ac={ glass:"oi" } var ad=Object.assign(ac,aa,ab) console.log(ad)
最终输出的ad:{name:"pol",glass:"sk",shit:"sk"},个人觉得,如果目标对是空对象,那么将源对象上的复制并覆盖过去可以说得通,如果是多个对象,就像上例中的那样,感觉其实更像是合并
对象的原型方法
Object.prototype.constructor;
通过这个方法返回目标对象的构造函数
var aoc=obj.constructor console.log(aoc);
输出:object
Object.prototype.toString()
经常用来检测对象类型
console.log(aoc.call(new Object)) //[object Object] console.log(aoc.call(new Date)); //[obejct Date] console.log(aoc.call(new String)) //[object String]
Obejct.prototype.valueof()
返回对象的原始值,具体示例如下:
var obj={ xaaa:"asd" }; Object.defineProperties(obj,{ name:{ //属性名 value:"joy", //属性值 configurable:false, //可删除可修改属性描述符 writable:false, //可写入修改 enumerable:true }, galss:{ value:function (a) { return a }, enumerable:true }, shit:{ value:"ul", enumerable:false } })
输出:{xaaa:"asd",name:"joy",galss:f(a),shit:'ul'}