JavaScript面向对象
属性类型
数据属性和访问器属性。
数据属性
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。
[[Enumerable]]:表示能否通过for-in循环返回属性。
[[Writable]]:表示能否修改属性的值。
[[Value]]:包含这个属性的数据值。
Object.defineProperty(属性所在的对象,属性的名字,一个描述符对象)
描述符对象的属性必需是:configurable、enumerable、writable、value。
访问器属性
不包含数据值;包含一对getter和setter函数。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。四个特性
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。
[[Enumerable]]:表示能否通过for-in循环返回属性。
[[Get]]:在读取属性时调用的函数。
[[Set]]:在写入属性时调用的函数。
创建对象
工厂模式
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 p1 = createPerson("aaa", 20, "aaa");
缺点:无法解决对象识别的问题
构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name);}
}
var p1 = new Person("aa",2, "SSS");
上述方法的缺点:函数实例的重复
解决办法是:函数提到外面,但是这样会导致全局作用域函数太多。
原型模式
通过原型模式来共享实例属性和方法。
function Person = {};
Person.prototype.name = "AAA";
Person.prototype.age = 20;
Person.prototype.sayName = function (){
alert(this,name):}
var p1 = new Person();
缺点:所有实例默认情况下取得相同的属性值;共享引用属性带来问题。
组合模式
构造函数中定义属性,原型中定义共享的属性和方法。
寄生构造函数模式
继承
原型链
实现继承的方法。基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例都喊喊一个纸箱原型对象的内部指针。如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个纸箱另一个原型的指针。相应的,另一个原型中也包含着另一个指向另一个构造函数的指针。层层递进,构成了实例与原型的链条。
主要的问题:包含引用类型的原型,参数。
借用构造函数
使用apply
组合继承(伪经典继承)
function SuperType(name){
this.name = name;
this.color = ['red', 'blue'];
}
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);
}
原型式继承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
寄生式继承
寄生组合式继承
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name){
this.name = name;
this.color = ['red', 'blue'];
}
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;
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
alert(this.age);
}