基于《javascript 面向对象精要》整理下思路:
ECMA5 对象的定义是无序属性的集合,属性可以是基本值,对象(包含函数),属性都有一个名字,名字可以是标识符或者是字符串,映射到属性。所以对象也可说是一组名字/属性的组合。
有两种方式创建对象:构造函数,字面量;
//构造函数,先定义,在赋值
var obj1 = new Object();
obj1.name = 'obama';
//字面量,直接赋值
var obj2 = {
name : 'bush'
}
读取属性也有两种方式
obj1.name //常用的是使用 . 点号直接读取属性
obj1['name'] //使用中括号里面是属性的字符串(有引号)也可以读取
//如果属性包含空格或者其他的非合法标识符就只能使用中括号,
属性有两种:
1,数据属性 named data property
2,访问器属性 named accessor property
两者的区别,先看数据属性的例子
var obj = {
name : 'obama'
}
obj.name;
consle.log(obj.name) //obama
//正常情况下,直接访问obj.name 不会输出任何结果,只是引擎访问这个属性,等待下一步的操
//作,如果有下一步操作,就把这属性的值返回出来,提供使用如:console.log()。
也就是说,数据属性包含属性的具体的值,我们可以访问,访问器属性则没有,只供引擎使用,
那么如何描述这两个属性呢,那就是特性,attribute(描述对象属性的属性),正常情况下,不可访问,在内部用[[ ]]包裹。如果想要访问,就用专用的方法,
Object.getOwnPropertyDescriptor(object,property)包含两个参数(对象名称,属性名称),返回一个对象包含具体的特性。
var obj = {
name : 'obama'
}
var properties = Object.getOwnPropertyDescriptor(obj,'name');
console.dir(properties);
可以看到有四个属性,这些就是属性的数据属性,我们可以访问的到的,也是可以修改的,使用两个特殊的方法
Object.defineProperty(); 定义单个对象的属性
Object.defineProperties(); 定义多个对象的属性
记住使用以上两个函数,会对把有真假值特性默认为false,而正常JS里都是true,如果定义的属性不存在就会创建新的属性!!
var obj1 = { };
Object.defineProperty(obj1,'name',{
configurable : true, //决定其他特性是否可以修改,包含直接删除delete属性值即value;
enumerable : true, //是否可以枚举
writable : true, //value 是否可以修改
value : 'obama' //对象属性真正保存值的地方,上面的都是对它的描述
}
);
var obj1 = {
name : 'obama'
}
上面的两个对象是相等的,我们在直接些对象字面量的同时,JS引擎就默认生成了上面的属性,我们也可以修改下
var obj1 = { };
Object.defineProperty(obj1,'name',{
configurable : true,
enumerable : false,
writable : true,
value : 'obama'
}
);
//下面的函数需要是枚举特性才能使用
obj1.propertyIsEnumerable('name'); //false
console.dir( Object.keys(obj1)); //数组是空
var properties;
for(properties in obj1){
console.log('it has been search') // undefined
}
//*以下是误区,in和hasOwnProperty函数查找的是否有属性,不论是否可以枚举*
console.log('name' in obj1); //true
console.log(obj1.hasOwnProperty('name')) //true
当然我们也可以同时定义多个属性
var obj = { };
Object.defineProperties(obj,{
name:{
configurable : true,
enumerable : true,
writable : true,
value : 'obama'
},
age :{
configurable : true,
enumerable : true,
writable : true,
value : 77
},
behavior: {
configurable : true,
enumerable : true,
writable : true,
value : function(){
alert('i am the presdent of Amerca')
}
}
});
obj = {
name : 'obama',
age : 77,
behavior : function(){ alert('i am the presdent of Amerca')}
}
下面说说访问器属性,目前没有方法,直接查看所有的特性,但是我们可以设置特性,和数据属性使用一样的方法,没有value 和writable这两个属性,但是多[[get]]和[[set]]的方法;
//字面量
var obj = {
_name : 'obama', //使用下划线_ 只是约定成俗的写法,表示私有的(实际上我们也能访问)
get name(){ //get 后面的name就是我们可以访问正常的属性,
return this._name;
},
set name(value){
this._name = value;
}
};
//或者使用函数
var obj = {
_name : 'obama'
};
Object.defineProperty(obj,'name',{
get : function (){
return this._name;
},
set : function(value){
this._name = value;
},
configurable : true,
enumerable : true
})
console.log(obj.name) //obama
访问器属性有趣的地方在于如果我们把get的方法换成其他,比如不返回它的值
get : function(){
return console.log(’i am Kim Jong-un‘);
}
obj.name //即使只是写出这个属性也会输出’i am Kim Jong-un’
我们通过obj.name永远得不到想要的值,当然这样设置没有任何意思,只是了解JS是如何取得属性的值,
同时设置数据属性和访问器属性是会得到一个错误。
属性首次添加给对象时,JS就会在对象上调用[[Put]]方法,在对象内部开辟新的节点保存属性,这个新属性有默认的特性,重点是这个属性仅会保存在这对象上,也就是说是这个对象的自有属性!自有!自有![[Extensible]]方法,确定对象是否可以扩展,有三个具体的方法:
1,禁止扩展
var obj = {
name : 'obama'
};
Object.preventExtensions(obj);
obj.age = 77;
console.log(obj.age) //undefined;
//无法增加属性,但是可以修改删除原有属性
Object.isExtensible(obj) //false 表示不可以扩展!
2,对象封印
var obj = {
name : 'obama'
};
Object.seal(obj); //不仅不可以扩展也不可删除属性,只能读写
delete obj.name //false
obj.name = ' Kim Jong-un';
console.log(obj.name) // Kim Jong-un
//可以修改属性的writable(修改后只能读取),只能true ->false,不能false ->true;
Object.isSealed(obj); //true;
Object.isExtensible(obj) //false;
3,对象冻结
var obj = {
name : 'obama'
};
Object.freeze(obj); //冻结后只可以读取值,,不可以修改删除值
Object.isFrozen(obj) //true;
Object.isSealed(obj); //true;
Object.isExtensible(obj) //false;
对象还有一个实用的方法,Object.getOwnPropertyNames();在对象本身的属性不可以枚举的情况下也能列出,返回一个数组,对比Object.keys() 只能列举可以枚举的.
注:上面的例子在严格模式下会抛出错误,非严格模式会失败
使用构造函数创建对象存在一个问题,就是必须使用new 操作符,构造函数也是函数如果直接调用的话,会把内部的this作用域指向全局;
function Fn(args){
this.args = args;
}
var obj1 = Fn('test');
obj1 //undefined
args //test
var obj2 = new Fn('test');
obj2.args //test;
//安全的构造函数
function Fn(args){
if( this instanceof Fn){
this.args = args;
}else{
return new Fn(args)
}
}
//也可以使用Object.creat()的方法来创建对象
var obj1 = { };
var obj2 = Object.create(null);
//obj2是一个真正意义上空的对象,没有任何的继承,比obj1更空,obj1继承Object对象的属性和方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。