属性类型
1,数据属性
var person = {
name : "Nicholas",
age : 29,
job : "SE",
sayName :function(){
alert(this.name);
}
]
[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。如上直接在对象上定义的属性,默认为true。
[[Enumerable]]表示能否通过for-in循环返回属性。如上直接在对象上定义的属性,默认为true。
[[Writable]]表示能否修改属性的值。如上直接在对象上定义的属性,默认为true。
[[Value]]包含这个属性的数据值。默认为undefined。
用Object.defineProperty()方法时,如果不指定,configurable,enumerable,writable特性的默认值都是false。
例如:
var person = {
name : "Nicholas"
};
[[Value]]特性将被设置为"Nicholas"
要修改属性默认的特性,必须使用ES5的Object.defineProperty()方法。这个方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable和value。设置其中一个或多个值,可以修改对应的特性值。
var person = {};
Object.defineProperty(Person,"name",{
writable : false, //将name属性设为只读~~
//configurable : false, 表示不能从对象中删除属性。一旦把属性定义为不可配置的,就不能再把它变回可配置了。此时,再调用Object.defineProperty()方法修改除writable之外的特性,都会导致错误。
value : “Nicholas”
});
alert(person.name); //Nicholas
person.name = "Greg";
alert(person.name); // Nicholas
2,访问器属性
访问器属性不包含数据值;它们包含一对getter和setter函数。
访问器属性也有四个特性:
[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认为true。
[[Enumerable]]表示能否通过for-in循环返回属性。默认为true。
[[Get]]读取属性时调用的函数。
[[Set]]写入属性时调用的函数。
访问器属性不能直接定义,必须使用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
_year前面的下划线是一种常用记号,用于表示只能通过对象方法访问的属性。访问器属性year则包含一个getter函数和一个setter函数。getter函数返回_year的值,setter函数通过计算来确定正确的版本。因此,把year属性修改为2005会导致_year变成2005.这是访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化。
不一定非要同时指定getter和setter。只指定getter意味着属性不能写。
上面方法之前使用__defineGetter__() & __defineSetter__()来创建getter和setter。
Object.defineProperties()方法可以通过描述符一次定义多个属性。接收两个对象参数:第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应。例如:
var book = {};
Object.defineProperties(book,{
_year : {
value : 2004
},
edition : {
value : 1
},
year : {
get : function(){
return this._year;
},
set : function(newValue){
if(newValue > 2004){
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
3,读取属性的特性
Object.getOwnPropertyDescriptor()可以取得给定属性的描述符。接收两个参数:属性所在的对象和要读取其描述符的属性名称。返回值是一个对象。
如果是访问器属性,这个对象的属性有configurable,enumerable,get,set;如果是数据属性,这个对象的属性有configurable,enumerable,writable,value。
var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
alert(descriptor.value); //2004
alert(descriptor.configurable);//false
JS中,可以针对任何对象---包括DOM和BOM对象使用Object.getownPropertyDescriptor()方法。
4,构造函数模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.syaName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas",29,"SE");
内部流程:
1,创建一个新对象;
2,将构造函数的作用域赋给新对象,;(this就指向了这个新对象)
3,执行构造函数中的代码;(为新对象添加属性)
4,返回新对象;
特点:
没有显式的创建对象;
直接将属性和方法赋给了this对象;
没有return;
person1.constructor == Person~
以这种方式定义的构造函数是定义在Global对象中的。
构造函数与其他函数的唯一区别,就在于调用它们的方式不同。构造函数也是函数,不存在定义构造函数的特殊语法。任何函数,只要通过new操作符来调用,那它就可以作为构造函数。如果不通过new来调用,跟普通函数没区别。
5,原型模式
我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象。这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
例子:
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "SE";
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
person1.sayName(); // "Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName);//true
理解原型对象
只要创建了一个函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。如:
Person.prototype.constructor ->Person
[[Prototype]] :
person1、person2与构造函数没有直接关系,而是通过实例的内部属性[[Prototype]](指向Person.prototype)联系的。
alert(Person.prototype.isPrototypeOf(person1));//true
Object.getPrototypeOf(person1) == Person.prototype;
to be continue~~~~~~