第6章 面向对象的程序设计
6.1 理解对象
var person = Object();
person.name = "xiaohong";
person.age = 24 ;
person.sayname = function(){
alert(this.name);
};
6.1.1属性类型
ECMAScript中有两种属性:数据属性和访问器属性
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。
[[Configurable]]表示能否通过delete删除属性从而重新定义属性
[[Enumerable]]表示能否通过for-in循环返回属性
[[writable]]表示能否修改属性的值
[[Value]]表示这个属性的数据值
要更改属性默认的特性,必须使用Object.defineProperty()方法,接受三个参数:属性所在的对象、属性的名字和一个描述符对象,描述符对象的属性必须是confugurable、enumerable、writable、value,设置其中的一个或多个值可以修改对应的特性值
var persom{};
Object.defineProperty(person,"name",{
writable: false,
value: "Nicholas"
});
alert(person.name);// "Nicholas"
访问器属性包含getter和setter函数
[[Get]]在读取属性时调用的函数。默认值为undefined
[[Set]]在写入属性时调用的函数。默认值为undefined
6.1.2定义多个属性
可利用Object.defineProperties()这个方法通过描述符一次定义多个属性
6.1.3读取属性的特性
可利用Object.getOwnPropertyDescriptor()方法取得给定属性的描述符
6.2 创建对象
Object构造函数创建对象:
var person = Object();
person.name = "xiaohong";
person.age = 24 ;
person.sayname = function(){
alert(this.name);
};
字面量形式创建对象:
var person = {
name: “小红”,
age: 24,
sayname:function(){
alert this.name;
}
};
工厂模式:
function creatperson(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 = creatperson ( "Nicholas", 29, "Software Engineer");
};
6.2.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( "Nicholas", 29, "Software Engineer");
var person2 =new person( "N小红", 24, "Software Engineer");
构造函数相比工厂模式有以下不同之处:没有显示创建对象,直接将属性和方法赋值给力this,没有return语句。
构造函数每个Person实例都会包含一个不同Function实例,会导致不同的作用域链和标识符解析。然而创建两个完成同样任务的Function实例没有必要。因此出现了原型模式来解决这个问题。
6.2.3原型模式
在实例中创建该属性将会屏蔽原型中的属性。
使用hasOwnProperty()方法可以检测一个属性是否存在于实例中,还是存在于原型中
两种使用in操作符的场合:单独使用或for-in循环中
单独使用:in操作符会在通过对象能够访问给定属性时返回true
简单的原型语法:
function Person(){}
Person.prototype = {
name: 'xioahong',
age: 24,
sayName: function(){
alert(this.name);
}
}
6.2.4 组合使用构造函数模式和原型模式
构造函数模式定义实例属性,而原型模式定义方法和共享的属性
6.2.5动态原型模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != function){
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
6.2.6 寄生构造函数模式
这种模式的基本思想是创建一个函数,该函数的作用是封装创建对象的代码,然后再返回新创建的对象
6.3 继承
oo语言支持两种继承方式:接口继承和实现继承
原型链有两个问题:引用类型的值会被所有实例共享,在创建子类型的实例时不能向超类型的构造函数传递参数,没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。
6.3.2借用构造函数
function Super(){
this.colors = [‘red’, ‘blue’, ‘green’];
}
function Sub(){
Super.call(this);
}
6.3.3组合继承
组合继承有的时候叫伪经典继承。指的是原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承,是最常用的一种继承方式
6.3.4原型式继承
6.3.5寄生式继承
6.3.6寄生组合式继承
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.sayAge = function(){
alert(this.age);
}