1. 原型继承
// 原型中存在的引用类型 会出现数据修改的问题,子类都指向的同一个内存空间
// 子类类型对象无法给父类传参数
function Test( age ) {
this.family = [ '妈妈' , '爸爸' ];
this.age = age;
}
function util(){}
util.prototype = new Test( 20 ); // 原型继承,原型链的第一种写法
var ul1 = new util();
ul1.family.push('姐姐');
var ul2 = new util();
console.log( ul2.family ); // 妈妈爸爸姐姐
2. 对象冒充
A:解决prototype 指向同一内存的问题
function Test( age ) {
this.family = [ '妈妈' , '爸爸' ];
this.age = age;
}
function util( age ){
Test.call( this , age ); // 对象冒充
}
var ul1 = new util( 21 );
ul1.family.push('姐姐');
var ul2 = new util( 22 );
console.log( ul2.family ); // 妈妈爸爸
alert( ul2.family ); // 妈妈爸爸
B:
function test( age ) {
this.family = [ '妈妈' , '爸爸' ];
this.age = age;
this.fun = function() {
return this.age+this.family ;
}
}
function util( age ){
test.call( this , age ); // 这里的对象冒充,会让 fun 函数也指向不同的内存空间 , 然而 fun 函数是应该共享的
}
var ul1 = new util( 21 );
var ul2 = new util( 22 );
console.log( ul1.fun == ul2.fun ); // false ,
3. 组合继承 对象冒充B的变形
function Test( age ) {
this.family = [ '妈妈' , '爸爸' ];
this.age = age;
}
Test.prototype.fun = function(){ // 然而只这样util 时并没有test 的原型的 ,只有这个并不能让ul1 使用fun方法
return this.age + this.family;
}
function util( age ){
test.call( this , age ); // 这里的对象冒充,会让 fun 函数也指向不同的内存空间 , 然而 fun 函数是应该共享的
}
util.prototype = new Test(); // 加上这个原型继承就可以使用而
var ul1 = new util( 21 );
var ul2 = new util( 22 );
console.log( ul1.fun == ul2.fun ); // true,
4.原型式继承
function getObj( o ) { // 原型链的第二种写法,函数写法
function F(){}
F.prototype = o;
return new F();
}
// 原型对象
var person = {
name : "tom",
family : [ "爸爸", "妈妈"]
};
var obj1 = getObj( person );
var obj2 = getObj( person );
obj1.family.push( "姐姐" );
console.log( obj2.family ); // 妈妈爸爸姐姐
5. 寄生式继承
function getObj( o ) { // 原型链的第二种写法,函数写法
function F(){}
F.prototype = o;
return new F();
}
function createObj( o ) {
// 这里不添加new 符号是不行的哦
var obj = new getObj( o ); // 这里生成新的一个空间来接受 getObj() 返回的对象 ,下面依然会与原型脸一样出现数据修改问题,因为family依然是原型链继承来的
obj.arr = [ "html" , "css" ]; // 这里重写arr类型,这样 每次调用createObj 时都会给这个新对象 创建一个空间来放arr不属于原型链属性但是能继承,不会出现数据修改问题
obj.getName = function(){
console.log( this.name );
};
return obj;
}
// 原型对象
var person = {
name : "tom",
family : [ "爸爸", "妈妈"]
};
var obj1 = new createObj( person );
var obj2 = createObj( person );
obj1.getName();
obj1.family.push( "姐姐" );
console.log( obj2.family ); // 妈妈爸爸姐姐
obj1.arr.push("javascript");
console.log( obj1.arr ); // html css javascript
console.log( obj2.arr ); // html css
6. 寄生组合继承 解决了组合继承两次使用person函数的问题
function getObj( o ) {
function F(){}
F.prototype = o;
return new F();
}
function createObj( Person , Student ) { //修改这个生产函数
var obj = getObj( Person.prototype ); // 这里吧Person的原型作为F的原型(o)进行了传递 , 返回的F 就是这里的 obj
obj.constuctor = Student; // console.log( stu1.constuctor ) // function student(){ person,call(this,age)} ,
Student.prototype = obj;
obj.arr = [ "html" , "css" ];
}
// 原型对象
function person( age ) { // 每个对象各自都有的属性定义在 构造函数上
this.age = age;
this.family = [ "爸爸", "妈妈"];
}
person.prototype.getAll = function(){ // 需要共享的定义在原型上
console.log( this.age + "..." + this.family );
};
person.prototype.setAge = function ( _age ) {
this.age = _age;
};
function student( age ){
person.call( this , age ); // 第二次使用person函数
}
createObj( person , student ); // util.prototype = new test(); // 第一次使用person函数
var stu1 = new student( 21 );
var stu2 = new student( 32 ) ;
stu1.family.push("弟弟");
console.log( stu1.family );
console.log( stu2.family );
stu1.getAll();
stu1.setAge( 33 );
console.log ( stu1.getAll === stu2.getAll) // true
console.log( stu1.getAll );
console.log( stu1.constructor ); // function person(){...} ,而不是student的构造函数</pre><br>