/*
面向对象的程序设计
面向对象(Object-Oriented,OO)语言有一个标志,那就是它们度要类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。
1理解对象
创建自定对象最简单的方式就是创建一个Object的实例,然后再为它添加属性和方法
*/
//对象字面量的方法
var person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function(){
alert(this.name);
}
var person = {
name:"Nicholas",
age:29,
job:"Software Engineer",
sayName:function(){
alert(this.name);
}
}
数据属性
要修改默认属性的特性,必须使用ECMAScript5的Object.defineProperty()方法。这个方法接受三个参数:属性所在的对象,属性的名字和一个描述符对象。其中描述符对象的属性必须是configurable,enumerable,writable,value。设置其中一或多个值,可以修改对应的特性值
configurable: 表示能否通过delete删除属性从新定义属性,能否修改属性的特性,能否把属性修改为访问器属性。
var person = {};
Object,defineProperty(person,"name",{
writable: false,
value: "Nicholas"
})
alert(person.name); //"Nicholas"
person.name = "Greg";
alert(person.name); //"Nicholas"
访问器属性
访问器属性不包含数据值;他们包含一对儿getter和setter函数,在读取访问器属性时,会调用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;
创建对象
虽然Object构造函数或字面量可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象会产生大量的重复代码。未解决这个问题,人们开始使用工厂模式的一种变体。
工厂模式
用函数来封装特定接口创建对象的细节
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 = createPreson("Nicholas",29,"Software Engineer");
var person2 = createPerson("Greg",27,"Doctor");
构造函数模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
}
}
var person1 = new Person("Nicholas",29,"Software Engineer");
var person2 = new Person("Nicholas",29,"Greg",27,"Doctor");
创建Person的新实例,必须使用new操作符
(1)创建一个新对象
(2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
(3)执行构造函数中的代码(为这个心对象添加属性)
(4)返回新对象
原型模式
我们创建的每个函数度有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "software enginner";
Person.peototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName();
理解原型对象
只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。
在默认的情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包括一个指向prototype属性所在函数的指针。
Person.prototype.constructor指向Person。而通过这个构造函数,我们可以为原型对象添加其他属性和方法
hasOwnProperty()方法可以检测一个属性是否存在于实例中,还是存在原型中。
取得对象上所有可枚举的实例属性 Object.keys()方法,这个方法接受一个对象作为参数,返回包含所有可枚举属性的字符串数组:
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "software enginner";
Person.peototype.sayName = function(){
alert(this.name);
};
var keys = Object.keys(Person.prototype);
console.log(keys) ; //"nam,age,job,sayName"
组合使用构造函数模式和原型模式
创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。
1构造函数模式用于定义实例属性
2原型模式用于定义方法和共享属性
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends = ["Shelby","count"];
}
Person.prototype={
constructor:Person,
sayName: function(){
console.log(this.name);
}
}
var person1 = new Person("Nicholas",29,"software engineer");
var person2 = new Person("Greg",19,"doctor");
Person1.friends.push("Van");
实例属性都是在构造函数中定义,而所有实例共享的属性constructor和方法都市在原型中定义
构造函数定义实例属性,原型模式定义方法和共享属性这种混合模式,比较广泛
继承 ECMAScript只支持实现继承,而且主要依靠原型链继承
每个构造函数度有一个原型对象,原型对象度包含一个指向构造函数的指针,实例包含一个指向原型对象的内部指针。假如一个原型有事另一个类型的实例这样层层递进构成实例和原型的链条。
function SuperType(){
this.prototype=true;
}
SuperType.prototype.getsuperValue = function(){
return this.prototype;
}
function SubType(){
this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue =function(){
return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());
组合继承
function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
}
function SubType(name,age){
//继承属性
SuperType.call(this,name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("Nick",29);
instance1.colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //Nick
instance1.sayAge()//29