对象的创建
使用对象直接量
对象直接量是由若干个键值对组成的映射表,键值对之间使用逗号隔开,映射表使用花括号包裹起来。
like:
var obj = {
x:12,
y:123,
z:1234,
'first name':'obj one'//如果属性名包含空格使用引号包裹起来,最后一个属性后的逗号可以省略。
}
通过new创建对象
function List(element){
var item = [];
this.add = function(element){
item.push(element);
return item;
}
}
var obj = new Object();
var arr = new Array();
var d = new Date();
var r = new RegExp();
var list = new List(); //可以创建自定义构造函数
console.log(list.add(1)); //[1]
Object.create()
它也可以创建一个新对象,其中第一个参数是这个对象的原型,第二个参数是对这个对象属性的进一步描述。
我们可以将上面的代码全部使用该方法进行修改:
function List(element){
var item = [];
this.add = function(element){
item.push(element);
return item;
}
}
var obj = Object.create(Object.prototype);
var arr = Object.create(Array.prototype);
var d = Object.create(Date.prototype);
var r = Object.create(RegExp.prototype);
var list = Object.create(List); //也可以创建自定义构造函数
console.log(list.prototype);
控制台输出:
属性的查询及设置
可以通过.或者[]来获取属性值。
var obj = {};
obj.name = 'Bob';
obj.age = 23;
控制台操作:
继承
在JavaScript中,如果我们需要查询对象中有某个属性,就会先查询该对象的自有属性是否含有该属性,否则就会顺着原型链一直想上查找,直到链的顶端。可以发现,继承使用过原型链来实现的。就像人们继承了祖辈的DNA一样,这里的DNA就是原型链,属性就像是某一段DNA片段。
var o = {x:1};
var p = Object.create(o);
p.y = 2;
var q = Object.create(p);
console.log(q.x + q.y); //3
如果继承来的属性名与新创建的属性具有相同的属性名,那么新创建的属性会覆盖之前的属性值
属性访问错误
- 查询对象的不存在属性会返回undefined,查询不存在对象的属性会报错。
- 对一个值属性的属性进行查询必须保证该值与该值的属性都是对象。
//较冗余的判断方法
var len = undefined;
if(book){
if(book.subtitle) len = book.subtitle.length;
}
//简练版
var len = book && book.subtitle && book.subtitle.length
- 给null与undefined设置属性会报类型错误
- 有的属性是只读的,不能重新赋值,有的对象不允许添加新的属性。
删除属性
delete可以删除对象的属性,但是delete只能够删除自由属性,不能删除继承属性,如果你删除继承属性,它并不会报错。因为delete删除成功或者没有副作用的时候,返回的是true。如果要删除该属性,必须在其定义这个属性的对象上进行删除操作。
举个栗子:
var o = {x:1};
var p = Object.create(o);
p.y = 2;
console.log(delete p.x);
console.log(p.x);
console.log(delete o.x);
console.log(p.x);
控制套输出:
注意:delete不能删除可配置性为false的属性。通过变量声明的对象也是不可删除的
(function(foo){
var boo = 1;
console.log(delete boo); //false
console.log(delete foo); //false
})(1);
属性检测
- in运算符:左侧为属性名,右侧为对象,如果该对象有该属性,就返回true,否则返回false
- hasOwnPreperty():检测时候为对象的自有属性,是返回true,否则返回false;
- propertyIsEnumberable():只有这个属性为自有属性并且是可枚举时,返回true;
- 使用 !== 判断是否等于undefined(需要注意的是这里的属性值不能够是undefined);
栗子:
var o = {x:1,y:undefined};
控制台操作:
属性枚举
- for/in循环可以遍历所有可枚举属性(包括自有属性和继承属性)
- Object.keys()返回一个数组,这个数组有对象中可枚举的自由属性的名称组成
- Object.getOwnPropertyNames()返回对象的所有自有属性的名称
var o = {x:1,y:2,z:3};
for(p in o){
console.log(p);
}
console.log(Object.keys(o));
console.log(Object.getOwnPropertyNames(o));
控制台输出:
属性getter与setter
意义:getter与setter是从面向对象中引出来的,很好的诠释了封装和安全性带来的优势。
从字面就可以看出,getter表示取,setter表示存。一个属性当具有两个方法时是读写属性,只有getter为只读属性,只有setter为只写属性。
关于安全性
var o = {
x: 1,
get data(){return this.x}
}
o.data = 2;
console.log(o.data); //1
var o = {
x: 1,
get data(){return this.x},
set data(x){ this.x = x;}
}
console.log(o.data); //1
o.data = 2;
console.log(o.data); //2
关于封装性
var o = {
x: 1,
y: 2,
get data(){return this.x + this.y}
}
console.log(o.data); //3,可以很方便的修改返回值出现的地方
属性的特征
- 数据属性的四个特征:value、writable、enumerable、configurable;
- 存取器属性四个特征:set、get、enumerable、configurable;
- 使用Object.getOwnPropertyDescriptor()方法可以查询属性特征
- 通过调用Object.defineProperty()方法可以创建修改对象属性,如果像同时修改多个属性的特性可以使用Object.defineProperties()方法
var o = {
x: 1,
y: 2,
get data(){return this.x + this.y}
}
控制台:
对象的三个属性
- 原型属性:使用isPrototyprOf()来检测
- 类属性:是一个字符串,用以表示对象的类型信息,并没有直接的方法来获取它,可以使用toString()方法,但是要确保是正确版本的toString(),建议使用一下方法 。
function classof(obj){
if(o === null){
return 'Null';
}
if(o === undefined){
return 'Undefined';
}
return Object.prototype.toString.call(o).slice(8, -1);
}
- 可扩展性:表示是否给对象添加新属性 ,通过Object.isExtensible()来查询对象是否为可扩展。通过Object.preventExtensions()来设置可扩展性。可扩展性的目的是将对象锁定,也就是说当对象一旦被锁定,那么就不会转换成可扩展性。Object.seal()和Object.preventExtensions()类似,除了能将对象设置为不可扩展的,还可以将对象的所有自有属性都设置为不可配置的。Object.freeze()将更严格地锁定对象——“冻结”(frozen)。除了将对象设置为不可扩展和将其属性设置为不可配置之外,还可以将它自有的所有数据属性设置为只读。
序列化对象
对象序列化是指将对象的状态转换成字符串,或者将字符串还原成对象。JSON.stringify()和JSON.parse()用来序列化和还原对象。
注意:函数、正则、Error对象、undefined不能序列化和还原。只能序列化对象的可枚举属性。