分类
JavaScript对象分类:
内置对象:由ECMAScript规范定义的对象或类,例如:数组、函数、日期(Date())、正则表达式
宿主对象:是由js解释器所嵌入的宿主环境(比如Web浏览器)定义的。
自定义对象:是由运行中的js代码创建的对象
JavaScript属性分类:
自有属性:直接在对象中定义的属性
继承属性:是在对象的原型对象中定义的属性
创建对象
可以通过对象直接量、关键字new、Object.create()函数创建对象
(1)对象直接量:
最简单的创建对象方式
1 var empty = {}; 2 var point = {x:0,y:0}; 3 var point2 = {x:point.x,y:point.y+1}; 4 var book = { 5 "main title" : "Javascript", //属性名字有非法字符一定要用字符串形式(或者保留字(for等)也要用字符串) 6 "sub-title" : "the Guide", //同上 7 }
(2)new关键字创建对象
new后跟一个构造函数
1 var a = new Array(); //创建一个数组,和[]一样 2 var d = new Date(); //创建一个表示当前时间的Date对象 3 var r = new RegExp("js"); //创建一个可以进行模式匹配的RegExp对象
(3)Object.create()创建对象
这个方法的第一个参数是这个对象的原型,第二个参数可选,用以对对象的属性进行进一步描述。
这个函数是一个静态函数,使用方法:
var o1 = Object.create({x:1,y:2}); //o1继承了属性x和y
传入参数如果为null,则会创建一个没有原型的新对象,它不会继承任何东西,甚至不包括基础方法,比如:toString(),也就是说它将不能和“+”运算符一起正常工作。
模拟原型继承:
1 function inherit(p){ 2 if(p==null) throw TypeError(); //若原型对象不存在,则返回错误 3 if(Object.create) 4 return Object.create(p); //若存在这个函数,则直接调用他创建对象 5 var t = typeof p; 6 if(t !== "Object" && t !== "function") throw TypeError(); //若传入的原型对象不是一个对象或者构造函数,则返回错误 7 function f(){}; //定义一个空的构造函数 8 f.prototype = p; //将其原型属性设置为p 9 return new f(); //返回f()创建p的继承对象 10 }
原型:
每一个JavaScript对象(null除外)都和“另外一个对象”相关联,这里的“另一个对象”就是原型对象,我们创建的所有对象都从它的原型对象那里继承属性。
(1)所有通过原型直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码Object.prototype获得对原型对象的引用。
(2)通过new Object()创建的对象也继承自Object.prototype,new Array()创建的对象继承自Array.prototype...
(3)没有原型的对象:Object.prototype,所有的对象都继承自该对象。
原型链:一个对象继承多个原型对象,这一系列的链接称为原型链。
属性的查询和设置:
访问属性值时的代码书写规范:
(1)对象名.属性名
(2)对象名["属性名"]
第二种方法可以看做是关联数组,即通过字符串作为下标访问属性,这样就可以很方便的更改属性名。这在很多情况下是很方便代码的编写的,比如属性名需要通过用户进行定义。
查询属性值时代码执行过程:
如果要访问的对象中不存在该属性,则会继续在该对象的原型对象中查询该属性,如果原型对象中也没有该属性,就继续在该对象的原型对象中查找,直到找到x或者查找到一个原型是null的对象为止。这样的查找过程构成了一个"链",也是通过这个链实现继承的。
属性的赋值的几种情况:
(1)如果该对象中已经有该属性,那么将会用新的值覆盖这个属性值。
(2)如果该对象中不存在该属性,赋值操作会给这个对象添加一个新的属性,并赋给它值。
(3)如果之前该对象继承自该属性,那么这个继承的属性就被新创建的同名属性覆盖。
注意:属性赋值操作首先检查原型链,以此判定是否允许赋值操作,例如,如果该对象继承自一个只读属性x,那么赋值操作是不允许的。如果允许属性赋值操作,它也总是在原始对象上创建属性或对已有的属性赋值,而不会去修改原型链。
属性的赋值在以下情况中会失败:
(1)o中的属性p是只读的:不能给只读属性重新赋值(definedProperty())方法中有一个例外,可以对可配置的只读属性重新赋值。
(2)o中的属性p是继承属性,且它是只读的:不能通过同名自有属性覆盖只读的继承属性。
(3)o中不存在自有属性p:o没有使用setter方法继承属性p,并且o的可扩展性是false。如果o中不存在p,而且没有setter方法可供调用,则p一定会添加至o中。但如果o不是可扩展的,那么在o中不能定义新属性。
属性的删除:
delete运算符可以对属性进行删除。它的操作数是一个属性访问表达式,需要注意的是,delete只是断开了属性和宿主之间的联系,而并没有属性中的属性进行操作:
1 a = {p:{x:1}}; 2 b=a.p; 3 delete a.p;
执行完这段代码后,b.x的值依然是1,所以在有些情况中属性的删除要遍历属性中的属性,依次删除,否则会造成内存泄露。
delete运算符只能删掉自有属性,不能删除继承属性,要删除继承属性只能从该对象的原型对象中删除,但要注意这会影响到所有继承该原型对象的对象属性。
delete运算符会返回一个值:
true:删除成功或者没有任何副作用时,即删除一个已经被删除或者不存在的属性或者删除一个非属性的值或者删除一个继承来的属性值
false:
1 delete Object.prototype; //不能删除,属性是不可配置的 2 var x = 1; //声明一个全局变量 3 delete this.x; //不能删除这个属性 4 function f(){}; //声明一个全局函数 5 delete this.f; //也不能删除全局函数