第六章 面向对象的程序设计
1.属性类型
a.数据属性
[[configurable]]:能否删除
[[enumerable]]:能否枚举
[[Writable]]:能否修改
[[Value]]:包含这个属性的数据值
修改默认的属性:Object.defineProperty()
b.访问器属性
[[configurable]]:能否删除
[[enumerable]]:能否枚举
[[Get]]:在读取属性时调用的函数
[[Set]]:在写入属性时调用的函数
访问器属性不能直接定义,必须调用Object.defineProperty(对象,属性名,修改内容)
注:可同时定义多个属性,
读取属性的方法:Object.getOwnPropertyDescriptor(对象,属性名),返回一个对象
2.创建对象
a.工厂模式——用函数来封装以特定接口创建对象的细节
function createPerson(name,age,job)
{
var o=new Object();
o.age=age;
o.name=name;
o.job=job;
o.sayname=function(){
alert(this.name);
};
return o;
}
b.构造函数模式——用构造函数来穿件特定类型的对象
function Person(name,age,job)
{
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
};
}
构造函数和普通函数区别:调用方式不同,通过new操作符调用
构造函数的问题:每个方法都要在每个实例上重新创建一次,可通过把函数定义到构造函数外部来解决
c.原型模式
1).原型对象:
当创建一个新函数,就会为该函数创建一个prototype属性,指向函数的原型对象。所有原型对象自动获得一个constructor属性,这个属性包含一个指向prototype所在函数的指针。
Person.prototype.constructor=Person
当调用构造函数创建实例后,实例的内部包含一个[[Prototype]]指针,指向构造函数的原型对象。
连接是存在于实例与构造函数的原型对象之间的。
方法:alert(Person.prototype.isPrototypeOf(person1)); //true ,确定是否是传入对象的原型对象
alert(Object.getPrototypeOf(person1)==person.prototype);//true,可以方便的取得一个对象的原型
alert(person1.hasOwnProperty.("name"));//true,检测属性在原型还是实例中
只能通过实例访问原型对象中的值,不能重写原型对象的值,只可以覆盖
2).语法——用一个包含所有属性和方法的对象字面量重写原型对象
function Person(){}
Person.prototype ={
constructor:Person,//注:因为完全重写了默认的prototype对象,constructor属性不再指向Person,所以这句有必要
name:"aqssfdgrf",
age:28,
job:"student",
sayName:function(){alert("this.name");}
};
3).in与for in
in:通过对象能访问到给定属性时返回true,无论在实例还是原型中
for-in:返回的是所有能够通过对象访问的,枚举的属性
keys():取得对象上所有可枚举的实例属性,接受一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。
Object.getOwnPropertyName():取得所有实例属性,无论能否枚举
原型的动态性:
实力与原型间是松散链接的关系,实例与原型之间的连接只不过是一个指针,重写原型对象切断了现有原型与任何之前已经存在的实例之间的联系
原型的缺点:因其共享的本质,对包含引用类型值的属性来说有很大问题
d.混合模式——构造函数模式与原型模式结合
构造函数定义实例属性,原型模式共享方法和共享的属性
e.动态原型模式
把所有的信息都封装在构造函数中,通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。
function Person(name,age,job)
{
this.name=name,
this.age=age,
this.job=job,
//方法,这段代码只有在初次调用构造函数时才会执行
if(typeof sayName!= "function")
{
Person.prototype.sayName=function(){
alert(this.name);
};
}
}
原型模式优点
1. 减少内存消耗,系统资源占用少,所有实例共享同一方法,不会创建多个
2. 原型对象继承时,子类在重写父类原型方法时很方便,可以很方便 调父类房法,再扩展。
原型模式缺点
1. 优点1既是最大的优点,也同样带来一个严重问题,如果共享的对象是引用对象(如array)则也会造成多个实例共享同一个array,很可能会相互影响
构造函数缺点
1. 每一次实例化,该对象内部函数都会被创建一遍。
2. 对象继承并需要在子类中调用父类的方法是不可能的,只可以覆盖或者使用。
优点:
每个实例的公共对象都是不同的,不会相互影响。
3.实现继承——依靠原型链继承实际的方法
a.原型链
基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法
本质是重写原型对象,代之以一个新类型的实例
确定原型和实例的关系:a)instanceof b)isPrototypeOf()
注:给原型添加方法一定要放在替换原型的语句之后
主要问题:a)来自包含引用类型值的原型 b)创建子类型的实例时,不能向超类型的构造函数中传递参数
b.借用构造函数——在子类型函数的内部调用超类型构造函数
call()和apply()——见收藏
优点:可以在子类型构造函数中向超类型构造函数传递参数
缺点:超类型中原型定义的方法对子类型不可见
c.组合继承——最常用
有关继承:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html