JavaScript权威指南学习笔记,禁止转载!
5、对象
对象的属性是无序的,每个属性都有一个字符串key和值value,
数据属性的标签:writable、enumerable、configurable、value
访问器属性的标签:enumerable、configurable、get、set。get表示属性可读,set表示属性可写。属性前面有下划线表示只能通过对象方法get/set访问的属性,也就是访问器属性。
(1)创建对象
1)字面量var obj={x:1,y:2};
2)new:var obj=new foo(); (obj的proto指向构造函数foo的foo.prototype)
如,function foo(){};
var obj=new foo();
typeof obj; //"object"
typeof obj.toString; //"function"(toString方法是obj原型链上Object.prototype上的方法)
注意:若(obj.z; //undefined)不代表obj对象及其原型链上没有属性z,可能有属性z但值是undefined。
3)Object.create(原型)
如,var obj= Object.create({x:1}); 此时{x:1}时obj的原型。
typeof obj.toString; //"function"
注意:但不是每个对象的原型链上都有Object.prototype,因此不是每个对象都有toString方法,如,var obj= Object.create(null); 此时null是obj的原型,也是原型链的顶端,因此,typeof obj.toString; //undefined
(2)属性操作
~~属性读:
如, var obj={x:1,y:2};
obj.x; //1
obj[“x”]; //1(不常用)
var p; for(p in obj){console.log(obj[p]); }
//1
//2
(这种方法会读出obj原型链上的属性,并且属性的顺序不确定。可以用hasOwnProperty过滤掉原型链上的属性。)
读属性会向原型链上查找。
~~检测属性是否存在:
obj.hasOwnProperty(属性名):判断对象obj自身上是否有该属性,返回true或false。
obj.propertyIsEnumerable(属性名):判断对象obj的该属性是否可枚举。原型链上的属性通常不可枚举。
(3)get/set方法和原型链
如,var obj = {};
Object.defineProperty(obj,'x',{value: 1,writable: false,configurable: false,enumerable: false});
var obj1 = Object.create(obj);
obj1.x = 10;
console.log(obj1.x); //1
当给对象的属性赋值时(obj1.x = 10;):
如果obj1上有x属性,修改其值。
如果obj1上没有x属性,会向其原型链查找,如果原型链上也没有x属性,那么x属性会被添加到obj1对象上;如果原型链上有x属性,则分三种情况:
a、原型链上x属性writable:true,会在obj1上添加x属性,并屏蔽原型链上的属性,
b、原型链上x属性writable:false,这条赋值语句会被忽略,如果是在严格模式下会报错,所以上述obj1.x还是1,
c、原型链上x有set/get方法,还是走原型链上的set/get方法,而不会给obj1上添加新的x属性。此时如果需要给obj1添加x属性,使用Object.defineProperty(obj1,’z’,{value:10,configurable:true});
MARK!
(4)属性标签
Object.getOwnPeopertyDescriptor(对象名,'属性名'):返回一个对象,包含这个属性的所有标签。
Object.defineProperty(对象名,”属性名”,属性的标签)(通过这个方法定义的属性,configurable、enumerable、writable的默认值为false)
如,var b={};
Object.defineProperty(b,'b',{configurable:false,writable:true});
Object.getOwnPropertyDescriptor(b,'b');//Object {value: undefined, writable: true, enumerable: false, configurable: false}
如,var person={};
Object.defineProperties(person,{
salary:{value:50000,writable:true},
promote:{
set:function(level){
this.salary*=1+level*0.1;
}
} //promote结束处
});
//Object {salary: 50000}
salary:50000
set promote:function (level)
__proto__:Object
person.promote=2; //调用set方法传值到函数的参数level
person.salary; //6000
Object.keys(对象):返回一个数组,包含该对象上的所有可枚举的属性名。
注意:如果writable:false,configurable:true,可以通过Object.defineProperties重新设置属性的value标签来变相地修改属性值;当然writable标签也可以被修改为true。
(5)对象标签
_proto_:原型
class:对象类型
Object.prototype.toString.call() 检测数据类型,包括对象的类型。
注意:Object.prototype.toString.call(new Number(1)); //"[object Number]"
Object.prototype.toString.call(1); //"[object Number]"
extensible:对象上的属性是否可被添加
Object.isExtensible(obj); 判断对象是否可扩展
Object.preventExtensions(obj); 使对象不可扩展
Object.seal(obj):使对象上属性configurable变为false
Object.isSealed(obj)判断
Object.freeze(obj):使对象上属性configurable和writable都变为false
Object.isFrozen(obj)判断
这些都不影响对象的原型链。
(6)对象序列化JSON
把对象转换为字节序列(数据以二进制序列的形式在网络上传送)的过程
JSON.stringify():将javascript值转换为JSON字符串,
如果属性值是undefined,将不会出现在结果字符串中;如果属性值是NaN或Infinity,会转换成null;如果是Date会转换为UTC时间格式,
如,var obj={x:1, y:true, z:[1,2,3], nullval:null, val:undefined, a:NaN, b:Infinity,c:new Date() };
JSON.stringify(obj);
//"{"x":1,"y":true,"z":[1,2,3],"nullval":null,"a":null,"b":null,"c":"2017-05-20T11:48:28.044Z"}"
序列化自定义
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}"
JSON.parse():将一个 JSON字符串转换为对象。
如,var str='{"x":1,"y":2}';
JSON.parse(str);
//Object {x: 1, y: 2}(单引号写在{}外面,每个属性名都必须要双引号,否则会抛出异常Uncaught SyntaxError: Unexpected identifier)
(7)valueOf、toString方法
如,var obj={x:1, y:2};
obj.toString=function(){return this.x+this.y; }
+obj; //3(+加号操作符强制将对象转换为基本类型)
obj.valueOf=function(){return this.x+this.y+100; }
+obj; //103
“result”+obj; //“result103”
当valueOf和toString方法都存在时,先查找valueOf,如果valueOf返回值为基本类型,以此为准,结束;如果valueOf返回值为对象再查找toString,如果toString返回值也为对象,就会报错。