日期:2014-05-16  浏览次数:20365 次

javascript面向对象总结

关于创建对象:

?

?

1:构造函数的方式

?

/**
 * 构造函数的方式 
 */
/**
 *构造方法 的缺点是,构造出的实例都会有一份方法(对象)。这是没必要的
 */
function Person(name,age){
	this.name=name;
	this.age=age;
	this.sayHello=function(){
		alert(this.name);
	}
}
var p=new Person("n",1);

?

?

2:构造与原型混合的方式

/**
 * 构造与原型混合的方式 
 */
/**
 *构造与原型混全合的方式实现了实例共用一份方法(对象)的功能。 
 */
function Person(name,age){
	this.name=name;
	this.age=age;
}
Persona.prototype={
	sayHello:function(){
		alert(this.name);
	}
}
var p1=new Person("x",1);
var p2=new Person("y",2);
alert(p1.sayHello===p2.sayHello);//true;

?

?

3:动态原型模式

/**
 * 动态原型模式 
 */
/**
 *动态原型模式将构造与原型混合的模式做了调整,组合到了一起,更优雅一些。 
 * @param {Object} name
 * @param {Object} age
 */
function Person(name,age){
	//属性
	this.name=name;
	this.age=age;
	
	//方法
	if(typeof this.sayHello != "function"){
		Person.prototype=function(){
			alert(this.name);
		}
	}
}

?

?

?

?

关于继承

1:原型链实现继承

?

/**
 *原型链实现继承
 * 1:原型链虽然很强大,可以用它来实现继承,但它也存在一些问题。其中,最主要的问题来自包含
 * 引用类型值的原型。
 * 引用类型值的属性会被所有的实例共享,所以一般会将它放在构造函数中,而不是放在原型对象中。但
 * 通过原型来实现继承时,原型实现上会变成另一个类型的实例。原先的实例属性也就顺理成章地变成了现在的原型属性
 * 2:在创建子类型的实例时,没有办法在不影响所有对象实例的 * 情况下,给超类型的构造函数传递参数。
 * 所以,实践中很少会单独使用原型链
 */

function SuperType(){
	this.colors=["red","blue","green"];
}

function SubType(){
	
}

SubType.prototype=new SuperType();

var s1=new SubType();
s1.colors.push("black"); //red,blue,green,black
alert(s1.colors);

var s2=new SubType();
alert(s2.colors);//red,blue,green,black

?

?

2:借用构造函数

?

/**
 *借用构造函数 
 */
/**
 *构造函数刚好可以解决原型链继承所面临的两个问题。但是构造函数也有缺点。
 * 方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,
 * 对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑这些问题,构造函数实现继承也是很少单独使用的。
 *  
 */
function SuperType(){
	this.colors=["red","blue","green"];
}
function SubType(){
	SuperType.call(this);
}
var s1=new SubType();
s1.colors.push("black");
alert(s1.colors); //"red,blue,green,black"

var s2=new SubType();
alert(s2.colors); "red,blue,green";

?

?

3:组合继承

?

/**
 *组合继承
 *   将原型链和借用构造函数组合到一块。使用原型链实现对原型属性和方法的继承,
 * 而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数利用,
 * 又能够保证每个实例都有它自己的属性。
 * 
 * 组合继承的缺点:
 * 无论什么情况下,都会调用两次超类型的构造函数:一次是在创建类型原型的时候,另一个次是在子类型的构造函数内部。
 * 不仅如此,超类型的属性会在子类型和原型里同时存在,这是没有必要的。
 */

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);
}

var s1=new SubType("n",1);
s1.colors.push("black");
alert(s1.colors);//red,blue,green,black

s1.sayName();
s1.sayAge();

var s2=new SubType("Greg",2);
alert(s2.colors);//red,blue,green,black
s2.sayName();
s2.sayAge();

?

?

?

4:寄生组合式继承

?

/**
 *寄生组合式继承 
 * 
 * 解决了组合继承的缺点,它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype
 * 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;
 */
function object(o){
	function F(){}
	Function.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.colors=["red","blue","green"];
}
SuperType.prototype.sayName=function(){
	alert(this.name);
}

function SubType(name,age){
	SuperType.call(this,name);
	this.age=age;
}

inheritPrototype(SubType,SuperType);

SubType.prototype.sayAge=function(){
	alert(this.age);
}
<