一、javascript对象概述
对象中包含一系列属性,这些属性时无序的.
每个属性都有一个字符串key和对应的value.
var obj={x:1,y:2};
obj.x;//1
obj.y;//2
var obj={};
obj[1]=1;
obj["1"]=2;
obj;//object{1:2}
obj[{}]=true;
obj[{x:1}]=true;
obj;//Object{1:2,[object Object]:true}
var obj={};
obj.y=2;
obj.x=1;
function foo(){};
foo.prototype.z=3;
var obj=new foo();
二、创建对象,原型链
1.对象创建-字面量
var obj1={x:1,y:2};
var obj2={
x:1,
y:2,
o:{z:3,n:4}
}
2.创建对象-new/原型链
function foo(){}//函数对象会默认带有prototype属性,改、该属性为一个对象属性,该对象也是有原型的,指向Object.prototype,Object.prototype也是有原型的,其值为null
foo.prototype.z=3;//为对象添加属性z=3
var obj=new foo();//创建新对象obj的原型会指向构造器的原型(即foo.prototype)
obj.y=2;
obj.x=1;
obj.x;//1
obj.y;//2
obj.z;//3
typeof obj.toString();//"function"
"z" in obj;//true
obj.hasOwnProperty("z");//false
//通过原型链的方法可以继承原型链上的属性,同时又不会修改原型链上的属性
3.对象创建-Object.create()
var obj=Object.create({x:1});//创建一个对象,并且对象的原型指向{x:1},{x:1}的原型指向Object.prototype,Object.prototype指向null
obj.x;//1
typeof obj.toString;//"function"
obj.hasOwnProperty("x");//false
并不是所有的对象都含有Object.prototype
var obj=Object.create(null);//此时obj的原型直接指向null,不包含Object.prototype,也不会包含Object的toString方法
obj.toString;//undefined
三、属性操作
1.属性读写
var obj={x:1,y:2};
obj.x;//1
obj["y"];//2
obj["x"]=3;
obj.y=4;
var obj={x1:1,x2:2};
var i=1,n=2;
for(;i<=n;i++){
console.log(obj["x"+i]);//1,2
}
var p;
for(p in obj){
console.log(obj[p]);
}
//注意:用for-in遍历时有可能会把原型链上的属性也遍历出来,并且其顺序不确定
2.属性读写-异常
var obj={x:1};
obj.y;//undefined
var yz=obj.y.z;//TypeError:Cannot read prototype "z" of undefined
obj.y.z=2;//TypeError:Cannot set property "z" of undefined
var yz;
if(obj.y){
yz=obj.y.z;
}
var yz=obj && obj.y && obj.y.z;//三个条件连接起来判断真假,都为真,则返回最后一个值;
3.属性删除
var person={age:28,title:"fe"};
delete person.age;//true
delete person["title"];//true
person.age;//undefined
delete person.age;//true,重复删除某个属性时,仍返回true
//注意:删除属性时返回true并不表示删除属性成功,而是表示该属性已经不存在了
delete Object.prototype;//false,每个属性会有一系列标签来控制它的权限
var descriptor=Object.getOwnPropertyDescriptor(Object,"prototype");
descriptor.configurable;//false,configurable表示是否可配置,其值为false决定了delete Object.prototype的值也为false并且不会生效
4.属性检测
var cat=new Object;
cat.legs=4;
cat.name="Kitty";
"legs" in cat;//true
"abc" in cat;//false
"toString" in cat;//true,inherited property!!!
cat.hasOwnProperty("legs");//true
cat.hasOwnProperty("toString");//false
cat.propertyIsEnumerable("legs");//true,是否可枚举
cat.propertyIsEnumerable("toString");//false
自定义一个属性,并让它的枚举标签为false
Object.defineProperty(cat,"price",{enumerable:false,value:1000});//Object.defineProperty中的enumerable默认为false
cat.propertyIsEnumerable("price");//false
cat.hasOwnProperty("price");//true
5.属性枚举
var o={x:1,y:2,z:3};
"toString" in o;//true
o.propertyIsEnumerable("toString");//false
var key;
for(key in o){
console.log(key);//x,y,z
}
var obj=Object.create(o);
obj.a=4;
var key;
for(key in obj){
console.log(key);//a,x,y,z
}
var obj=Object.create(o);
obj.a=4;
var key;
for(key in obj){
if(obj.hasOwnProperty(key)){
console.log(key);//a
}
}
四、get/set方法
例1:
var man={
name:"Bosn",
weibo:"@Bosn",
get age(){
return new Date().getFullYear()-1988;
},
set age(val){
console.log("Age can not be set to "+val);
}
}
console.log(man.age);//27
man.age=100;//Age can not be set to 100
console.log(man.age);//27
例2:
var man={
weibo:"@Bosn",
$age:null,
get age(){
if(this.$age==undefined){
return new Date().getFullYear()-1988;
}else{
return this.$age;
}
},
set age(val){
val= +val;//将字符串转为数字
if(!isNaN(val)&&val>0&&val<150){
this.$age=+val;
}else{
throw new Error("Incorrect val="+val);
}
}
}
console.log(man.age);//27
man.age=100;
console.log(man.age);//100
man.age="abc";//error:Incorrect val=NaN
get/set与原型链
function foo(){}
Object.defineProperty(foo.prototype,"z",{get:function(){return 1;}});
var obj =new foo();
obj.z;//1
obj.z=10;
obj.z;//1
//注意:obj的对象上没有z属性并且向上查找时有对于的get或set方法时,当我们尝试赋值时,实际上会走get或set方法
//通过下面的方法可以为当前对象添加属性
Object.defineProperty(obj,"z",{value:100,configurable:true});
obj.z;//100
delete obj.z;
obj.z;//1
var o={};
Object.defineProperty(o,"x",{value:1});//writable=false,configurable=false
var obj=Object.create(o);
obj.x;//1
obj.x=200;
obj.x;//still 1,can't change it
Object.defineProperty(obj,"x",{writable:true,configurable:true,value:100});
obj.x;//100
obj.x=500;
obj.x;//500
五、属性标签
通过Object.getOwnPropertyDescriptor("对象","属性")来查看对象属性的属性标签
例:Object.getOwnPropertyDescriptor({pro:true},"pro");//Object{value:true,writable:true,enumerable:true,configurable:true}
Object.getOwnPropertyDescriptor({pro:true},"a");//undefined
管理或设置属性标签
Object.defineProperty("对象","属性","属性标签对象")
Object.defineProperties("对象","复杂对象")
例1:
var person={};
Object.defineProperty(person,"name",{
configurable:false,
writable:false,
enumerable:true,
value:"Bosn Ma"
});
person.name;//Bosn Ma
person.name=1;
person.name;//still Bosn Ma
delete person.name;//false
Object.defineProperty(person,"type",{
configurable:true,
writable:true,
enumerable:false,
value:"Object"
});
Object.keys(person);//["name"],通过Object.keys()可以查看对象的属性
例2:
var person={};
Object.defineProperties(person,{
title:{value:"fe",enumerable:true},
corp:{value"BABA",enumerable:true},
salary:{value:50000,enumberable:true,writable:true}
});
Object.getOwnPropertyDescriptor(person,"salary");//Object{value:50000,writable:true,enumerable:true,configurable:false}
Object.getOwnPropertyDescriptor(person,"corp");//Object{value:"BABA",writable:false,enumerable:true,configurable:false}
例3:
var person={};
Object.defineProperties(person,{
title:{value:"fe",enumerable:true},
corp:{value:"BABA",enumerable:true},
salary:{value:50000,enumerable:true,writable:true},
luck:{
get:function(){
return Math.random()>0.5?"good":"bad";
}
},
promote:{
set:function(level){
this.salary*=1+level*0.1;
}
}
});
Object.getOwnPropertyDescriptor(person,"salary");//Object{value:50000,writable:true,enumerable:true,configurable:false}
Object.getOwnPropertyDescriptor(person,"corp");//Object{value:"BABA",writable:false,enumerable:true,configurable:false}
person.salary;//50000
person.promote=2;
person.salary;//60000
属性标签可以重复被设置:
var person={};
Object.defineProperty(person,"name",{
value:1111,
configurable:false//configurable为false时,除了writable从true改为false其他属性修改不允许
});
console.log(person.name);
console.log(Object.getOwnPropertyDescriptor(person,"name"));
Object.defineProperty(person,"name",{
enumerable:true
});
console.log(Object.getOwnPropertyDescriptor(person,"name"));
六、对象标签
对象标签主要有3个:[[proto]],[[class]],[[extensible]]
1.原型标签[[proto]]
2.class标签,没有直接的方法来查看class,可以通过Object.prototype.toString来间接地查看
var toSting=Object.prototype.toString;
function getType(o){return toSting.call(o).slice(8,-1);};
toSting.call(null);//"[object Null]"
getType(null);//"Null"
getType(undefined);//"undefined"
getType(1);//"Number"
getType(new Number(1));//"Number"
typeof new Number(1);//"object"
getType(true);//"Boolean"
getType(new Boolean(true));//"Boolean"
3.extensible标签表示对象是否可以扩展,属性是否可以添加
var obj={x:1,y:2};
Object.isExtensible(obj);//true
Object.preventExtensions(obj);
Object.isExtensible(obj);//false
obj.z=1;
obj.z;//undefined,add new prototy failed
Object.getOwnPropertyDescriptor(obj,"x");//Object{value:1,writable:true,enumerable:true,configurable:true}
Object.seal(obj);
Object.getOwnPropertyDescriptor(obj,"x");//Object{value:1,writable:true,enumerable:true,configurable:false}
Object.isSealed(obj);//true
Object.freeze(obj);
Object.getOwnPropertyDescriptor(obj,"x");//Object{value:1,writable:false,enumerable:true,configurable:false}
Object.isFrozen(obj);//true
序列化、其他对象方法
var obj={x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj);//"{"x":1,"y":true,"z":[1,2,3],"nullVal":null}"
obj={val:undefined,a:NaN,b:Infinity,c:new Date()};
JSON.stringify(obj);//"{"a":null,"b":null","c":"2015-01-20T14:12:45.910Z"}"
//注意:值为undefined时不会被显示,值为NaN和Infinity时显示为null,值为时间会被转为UTU的时间格式
obj=JSON.parse("{"x":1}");
obj.x;//1
序列化-自定义
var obj={
x:1,
y:2,
o:{
o1:1,
o2:2,
toJSON:function(){
return this.o1+this.o2;
}
}
};
JSON.stringify(obj);//"{"x:1,"y":2,"o":3}"
其他对象方法
var obj={x:1,y:2};
obj.toString();//"[object Object]"
obj.toString=function(){return this.x+this.y};
console.log("Result "+obj);//"Result 3" ,by toString
console.log(+obj);//3,form toString
obj.valueOf=function(){return this.x+this.y+100;};
console.log(+obj);//103,from valueOf
console.log("Result "+obj);//still "Result 103"