面向对象的程序设计
- ECMAScript中有两种属性:数据属性和访问器属性
数据属性包含一个数据值的位置 - 修改属性默认的特性,必须用Object.defineProperty(属性所属对象,属性名,描述符对象),其中描述符对象的属性必须是configurable,enumerable,writable和value。一旦把属性定义为不可配置的,就不能把它变回可配置的
- 访问器属性不包含数据值,包含一对儿getter和setter函数,读取访问器属性时,调用getter函数,写入时,访问setter函数
- 访问器属性只能用Object.defineProperty()定义
- Object.defineProperties(要添加属性的对象,属性对象)一次可添加多个属性
- 组合使用构造函数模式和原型模式时,使用构造函数定义实例属性,使用原型定义共享的属性和方法
创建对象
工厂模式
- 每个对象的实例都有一个constructor属性,指向构造函数
原型模式
- 我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型所有实例共享的属性和方法。
- prototype就是通过调用构造函数而创建的那个对象实例的原型对象
- 可以把对象想象成一个鸡蛋,原型就是蛋黄,对象的实例属性和方法就放在蛋清里面,在原型的基础上,添加属性和方法,就构成了以原型为基础的新对象
- 无论什么时候,只要创建一个新函数,就会根据特定规则为该函数创建一个prototype属性,这个属性指向函数的原型对象
- 每个实例内部包含一个指针[[Prototype]],指向实例的原型,即构造函数的原型对象prototype,一些浏览器中是proto属性.
- isPrototypeOf() 确定是不是一个实例对象的原型
- getPrototypeOf() 得到对象的原型引用
- 每当代码读取某个对象的某个属性时,都会执行一次搜索
- 首先搜索对象实例本身的属性
- 没有找到,继续搜索指针指向的原型对象
- 可以通过对象实例访问原型的值,但不能通过对象实例重写原型中的值
- hasOwnProperty()和in 操作符,就可以确定该属性时存在于对象中,还是原型中
function hasPrototypeProperyt(obj,name) { return !obj.hasOwnProperty(name) && (name in obj); }
- 构造函数的原型对象就是实例的原型
- 使用for-in循环时,返回的是所有能够通过对象访问的,可枚举的属性,即包括存在于实例中的属性,也包括存在于原型中的属性。
- 屏蔽了原型中不可枚举属性的实例属性也会在for-in循环中返回
- Object.keys(obj) 可取得对象上所有可枚举的实例属性,返回所有可枚举属性的字符串数组
- 实例中的指针仅指向原型,而不指向构造函数
- 重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系,它们引用的仍然是最初的原型
组合使用构造函数模式和原型模式----创建自定义类型最常见方式
- 构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性
继承
*继承主要依靠原型链来实现的,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法
原型链
- 继承是通过创建父类型的实例,并将该实例赋值给subtype.prototype(子类型的原型对象)实现的。实现的本质是重写原型对象,代之以一个新类型的实例
借用构造函数
- 在子类型的构造函数调用父类型的构造函数
SuperType.call(this);this指向新创建的实例,就会在新对象上执行父类型构造函数中定义的所有对象初始化代码
组合继承
子类型构造函数内调用父类型构造函数
supertype.call(this,参数) //子类型得到的属性也是实例属性
this.age = age; //定义子类型的实例属性
寄生组合式继承
- 被认为是引用类型最理想的继承范式
- 使用最多的继承模式是组合继承,这种模式使用原型链继承共享的属性和方法,而通过借用构造函数继承实例属性。
网友评论