属性类型
要修改对象的属性的默认的特性,必须使用Object.defineProperty() 方法。这个方法接受三个参数:属性所在的对象,属性的名字,一个描述符对象。
描述符对象的属性必须是configurable,enumberable,writable,value。在不指定情况下,configurable,enumberable,writable这三个属性都是默认为false。
configurable设置为false 表示不能从对象中删除属性。writable设置为false表示是只读的,不能对属性进行赋值。enumberable表示能否通过for-in循环返回属性。
访问器属性
在读取访问器属性时,会调用getter函数;在写入访问器属性时,会调用setter函数并传入新值。 访问器属性不能直接定义,必须使用Object.defineProperty()来定义。
var book={
_year:2004,
edition:1
};
Object.defineProperty(book,"year",{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
}
});
book.year=2005;
alert(book.edition);//2
定义多个属性:Object.defineProperties()方法。
读取属性的特征:Object.getOwnPropertyDescriptor()方法。
var book={
};
Object.defineProperties(book,{
_year:{
value:2004,
writable: true//这个必须写,不然不能下面book.year没有启用而起作用弹出2007,不然就弹出2004
},
edition:{
value:1
},
year:{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
},
}
});
var descriptor=Object.getOwnPropertyDescriptor(book,"_year");
alert(descriptor.value);//2004
alert(descriptor.configurable);//false
book.year=2007;
alert(book._year);//2007
创建对象
1.工厂模式:
function createPerson(name,age,job){
var o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function(){
alert(this.name);
};
return o;
}
var person1=createPerson("Nick",29,"Engineer");
var person2=createPerson("Greg",27,"Doctor");
person1.sayName();//Nick
alert(person2.name);//Greg
2.构造函数模式:
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
}
}
var person1=new Person("Nick",29,"Engineer");
var person2=new Person("Greg",27,"Doctor");
person1.sayName();//Nick
alert(person2.name);//Greg
3.原型模式
function Person(){
}
Person.prototype.name="Nike";
Person.prototype.age=29;
Person.prototype.job="Engineer";
Person.prototype.sayName=function(){
alert(this.name);
};
var person1=new Person();
person1.sayName();//Nike
var person2=new Person();
person2.sayName();//Nike
alert(person1.sayName==person2.sayName);//true
// 自定义hasPrototypeProperty
function hasPrototypeProperty(obj, property) {
return !obj.hasOwnProperty(property) && property in obj
}
hasOwnProperty() 方法可以检测一个属性是否存在于实例中,还是存在于原型中。如果存在于对象实例中,则返回true。
hasPrototypeProperty() 方法可以检测一个属性是否存在于实例中,还是存在于原型中。如果存在于对象原型中,则返回true。
Object.keys() 方法接受一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。
更简单的原型语法:
function Person(){
}
Person.prototype={
name: "Nike",
age: 29,
job: "Engineer",
sayName: function(){
alert(this.name);
}
};
原型对象的问题:
function Person(){
}
Person.prototype={
constructor: Person,
name: "Nike",
job: "Engineer",
friends: ["Shelby","Court"],
sayName: function(){
alert(this.name);
}
};
var person1=new Person();
var person2=new Person();
person1.friends.push("Van");
alert(person1.friends);//Shelby,Court,Van
alert(person2.friends);//Shelby,Court,Van
alert(person1.friends==person2.friends);//true
可以看到当改变一个对象的friends时,其他的对象的friends也跟着改变friends数组存在于person.prototype中,而不是存在于person1中,所以当改变person1的friends时候,person2的friends也变化。
4.组合使用构造函数模式和原型模式:构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends=["Shelby","Court"];
}
Person.prototype={
constructor: Person,
sayName: function(){
alert(this.name);
}
}
var person1=new Person("Nike",29,"Engineer");
var person2=new Person("Greg",27,"Doctor");
person1.friends.push("Van");
alert(person1.friends);//Shelby,Court,Van
alert(person2.friends);//Shelby,Court
alert(person1.friends==person2.friends);//false
alert(person1.sayName==person2.sayName);//true
5.动态原型模式
可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != "function") { //在sayName()方法不存在的情况下,才会将它添加到原型中。instanceof操作符也可以
Person.prototype.sayName = function() {
alert(this.name);
};
}
}
var friend = new Person("Nike", 29, "Engineer");
friend.sayName();//Nike