对象
- 对象可以看成是从字符串到值的映射。除了字符串、数字、true、false、null和undefined之外,javascript的值都是对象。
- 除了名字和值之外,每个属性还有一些与之相关的值,称为“属性特性”
- 可写(writable),表明是否可以设置该属性的值。
- 可枚举(enumerable),表明是否可以通过for/in 循环返回该属性。
- 可配置(configurable),表明是否可以删除或修改该属性。
- 对象的原型(prototype)指向另外一个对象,本对象的属性继承自它的原型对象。
- 自有属性是直接在对象中定义的属性
- 继承属性是在对象的原型对象中定义的属性。
创建对象
- 可以通过对象直接量、关键字new和Object.create()函数来创建对象。
- 对象直接量是一个表达式,这个表达式的每次运算都创建并初始化一个新的对象,每次计算对象直接量的时候,也都会计算它的每个属性的值。也就是说,如果在一个重复调用的函数中的循环体内使用了对象直接量,它将创建很多新对象,并且每次创建的对象的属性值也有可能不同。
- new运算符创建并初始化一个新对象。关键字new后跟随一个函数调用。这里的函数称作构造函数,构造函数用以初始化一个新创建的对象。
- 所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过Javascript代码Object.prototype获得对原型对象的引用。通过关键字new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值。
- Object.create()方法创建一个新对象,其中第一个参数是这个对象的原型。
// inherit() 返回一个继承自原型对象p的属性的新对象。
function inherit(p){
if(p===null) throw TypeError();
if(Object.create){
return Object.create(p)
}
var t = typeof p;
if(t!=="object" && t!=="function") throw TypeError();
function f(){}
f.prototype = p;
return new f();
}
复制代码
属性的查询和设置
- 对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。对于方括号来说([]),方括号内必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字。
- 属性赋值操作首先检查原型链,以此判断是否允许赋值操作。例如,如果o继承自一个只读属性x,那么赋值操作是不允许的。如果允许属性赋值操作,它也总是在原始对象上创建属性或对已有的属性赋值,而不会去修改原型链。在javascript中,只有在查询属性时才会体会到继承的存在,而设置属性则和继承无关。
删除属性
- delete只是断开属性和宿主对象的联系,而不会去操作属性中的属性。
- delete运算符只能删除自有属性,不能删除继承属性。
- 当delete表达式删除成功或没有任何副作用(比如删除不存在的属性时),它返回true,如果delete后不是一个属性访问表达式,delete同样返回true。
o = {x:1}
delete o.x // true
delete o.x // true
delete o.toString() // true
delete 1 // true
delete Object.prototype // 不能删除,属性是不可配置的
var x = 1;
delete this.x // 不能删除var定义的全局变量
function f(){}
delete this.f // 也不能删除全局函数
this.x = 1; // 创建一个可配置的全局属性(没有用var)
delete x // 将他删除
复制代码
检测属性
- in运算符的左侧是属性名(字符串),右侧是对象。如果对象的自有属性或继承属性中包含这个属性返回true
- 对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性。对于继承属性它将返回false。
- propertyIsEnumerable()是hasOwnProperty的增强版,只有检测到是自有属性且这个属性的可枚举性为true时它才返回true。
枚举属性
- 对象继承的内置方法不可枚举的,但是在代码中给对象添加的属性都是可枚举的
function extend(o,p){
for(prop in p){
o[prop] = p[prop]
}
return o;
}
function merge(o,p){
for(prop in p){
if(o.hasOwnProperty(prop)) continue;
o[prop] = p[prop]
}
return o
}
function restrict(o,p){
for(prop in o){
if(!(prop in p)) delete o[prop]
}
return o;
}
function subtract(o,p){
for(prop in p){
delete o[prop]
}
return o
}
function union(o,p){
return extend(extend({},o),p)
}
function intersection(o,p){
return restrict(extend({},o),p)
}
function keys(o){
if(typeof o !=="object") throw TypeError()
var result = [];
for(var prop in o){
if(o.hasOwnProperty(prop)){
result.push(prop)
}
}
return result;
}
复制代码
- Object.keys(),返回一个数组,这个数组由对象中
可枚举的自有属性的名称组成
。 - Object.getOwnPropertyNames(),返回对象的
所有的自有属性的名称
。
属性getter和setter
- javascript调用getter方法(无参数)。这个方法的返回值就是属性存取表达式的值。当设置值的时候调用setter方法。
属性的特性
- 数据属性的4个特性分别是它的值(value/get)、可写性(writable/set)、可枚举性(enumerable)和可配置型(configurable)
- 属性描述符对象的属性有上面四个,可以通过Object.getOwnPropertyDescriptor()可以获得。
- 可以通过调用Object.defineProperty()来定义对象的属性。
var o = {};
Object.defineProperty(o,"x",{
value:1,
writable:true,
enumerable:false,
configurable:true
})
o.x // 1
Object,keys(0) // [] 不可枚举
Object.defineProperty(o,"x",{writable:false})
o.x = 2; // 操作失败但不报错。
o.x // 1
Object.defineProperty(o,"x",{get:function(){return 0}})
o.x // 0
复制代码
- Object.defineProperty 这个方法要么修改已有属性要么新建自有属性,但不能修改继承属性。
对象的三个属性
原型属性
- 对象的原型属性是用来继承属性的。
- Object.getPrototypeOf() 可以查询一个对象的原型。
- 要想检测一个对象是否是另一个对象的原型(或处于原型链中),可以使用isPrototypeOf()
类属性
- 对象的toString() 方法返回一个这种格式的字符串[object class]
function classof(o){
if(o===null) return 'Null'
if(o===undefined) return 'Undefined'
return Object.prototype.toString.call(o).slice(8,-1)
}
复制代码
序列化对象
- JSON.stringify()和JSON.parse() 用来序列化和还原javascript对象。
o = {x:1,y:{z:[false,null,""]}}
s = JSON.stringify(o)
p = JSON.parse(s) // p是o的深拷贝
复制代码
- JSON.stringify()只能序列化对象可枚举的自有属性。对于一个不能序列化的属性来说,在序列化后的输出字符串会将这个属性省略掉。
- Object.prototype实际上没有定义toJSON()方法,但对于需要执行序列化的对象来说,JSON.stringify()方法会调用toJSON()方法。如果在待序列化的对象中存在这个方法,则调用它,返回值即是序列化的结果,而不是原始的对象。