继承的几种模式


// 继承方式1 ==> 默认的原型继承
function Person() {}
Person.prototype.run = function() {};
var xiaohong = new Person();

// 继承方式2 ==> 置换后的原型继承
function Person() {}
Person.prototype = {
say: function() {}
}
var xiaohong = new Person();

// 继承方式3 ==> 寄生式继承
var obj = { val: 100 };
var newObj = Object.create( obj );

// 继承方式4 ==> 混入继承
function extend( o1, o2 ) {
for( var key in o2 ) {
o1[key] = o2[key];
}
}
var o = { abc: 888 };
var o2 = { aaa: 111, bbb: 222, ccc: 333 };
extend( o, o2 );

// 继承方式5 ==> 对象冒充( 构造函数借用 )
function Person( name, age, sex ) {
this.name = name;
this.age = age;
this.sex = sex;
}

function Student( name, age, sex ) {
this.Person = Person;
this.Person( name, age, sex );
delete this.Person;
}

function Student( name, age, sex ) {
//Person.call( this, name, age, sex );
Person.apply( this, arguments );
}

var xiaohong = new Student('小红', 16);
console.log( xiaohong );

// 继承方式6 ==> 原型组合继承
function Person( name, age, sex ) {
this.name = name;
this.age = age;
this.sex = sex;
}

Person.prototype = {
run: function() {
console.log('人都会跑');
}
};

function Student( name, age, sex ) {
Person.apply( this, arguments );
}

// 解决方案1:
// 这样可以,但是不建议,因为一定会给Student添加一些额外的方法,
// 这些方法不应该和Person共享
//Student.prototype = Person.prototype;

// 解决方案2,混入继承,可取,用的也比较多
//extend( Student.prototype, Person.prototype );

// 解决方案3,原型寄生组合式继承
//Student.prototype = Object.create( Person.prototype );

// 解决方案4,
Student.prototype = new Person;

// xiaofang ==> Student.prototype ==> Person.prototype ==> Object.prototype ==> null
var xiaofang = new Student( '小芳', 17, '女' );
xiaofang.run();


/*
* 理想的继承解决方案:
* */
function Person( name, age, sex ) {
this.name = name;
this.age = age;
this.sex = sex;
}

Person.prototype = {
run: function() {
console.log('人都会跑');
}
};

function Student( name, age, sex ) {
Person.apply( this, arguments );
}

// 让学生实例,继承Student.prototype & Person.prototype
Student.prototype = Object.create( Person.prototype );

// 再给Student扩展自己独有的方法
extend( Student.prototype, {

} );

转载于:https://www.cnblogs.com/luxiaoxiao/p/6102977.html

### JavaScript 继承的方法 #### 1. 原型链继承 原型链是 JavaScript 实现继承的一种基本模式。在这种模式下,子类通过其原型(prototype)链接到父类的实例上。这样,当访问子类的一个属性或方法时,如果该属性或方法不存在,则会沿着原型链向上查找直到找到为止。 然而,这种方式存在一些缺点,比如所有子类型的实例都会共享同一个超类型实例上的属性,这可能导致意外的状态共享问题[^1]。 ```javascript function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function () { return this.property; }; function SubType() {} // 设置SubType的原型为SuperType的新实例 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; var instance = new SubType(); console.log(instance.getSuperValue()); // 输出: true ``` #### 2. 构造函数继承 (借用构造函数) 为了克服原型链的一些局限性,可以采用构造函数继承的方式。这种方法是在子类构造器内部调用父类构造器,并传递当前 `this` 上下文给它。这样做可以让每个子类都有自己的独立副本而不是共享父类的数据成员。 但是这种做法也有不足之处——无法复用父类定义好的公共方法;每次创建新对象都要重新执行一次完整的初始化过程[^3]。 ```javascript function Parent(name) { this.name = name || 'parent'; } Parent.prototype.sayName = function(){ console.log(this.name); }; function Child(name){ Parent.call(this,name); // 调用了父级构造函数并传入参数 } let childInstance = new Child('child'); childInstance.sayName(); // 报错,因为Child没有sayName这个方法 ``` 注意上述代码中虽然实现了数据层面的继承,但并没有复制父类原型上的方法。 #### 3. 组合继承 组合继承综合了前两种方式的优点:既可以通过构造函数获得私有属性的支持,又可以从原型链那里得到可重用的功能。具体来说就是先利用构造函数完成对实例属性的操作,再让子类的原型指向一个父类实例来获取公有的行为。 不过这也带来了重复调用父类构造器的问题 —— 创建子类实例时以及设置子类原型的时候各发生了一次. ```javascript function Parent(name) { this.name = name || 'parent'; this.colors = ['red', 'blue']; } Parent.prototype.sayName = function(){ console.log(this.name); }; function Child(name, age){ Parent.call(this, name); // 第二次调用Parent() this.age = age; } Child.prototype = new Parent(); // 第一次调用Parent(), 并且这里丢失了constructor指针 Child.prototype.constructor = Child; const kid = new Child('kid', 5); console.log(kid instanceof Child); // true console.log(kid instanceof Parent); // true console.log(kid.sayName === Parent.prototype.sayName); //true ``` #### 4. 寄生组合式继承 为了避免组合继承中存在的效率低下问题,寄生组合式继承应运而生。此技术只调用一次父类构造器即可达到目的,而且不会影响原有功能。其实现原理在于借助临时性的中间件作为桥梁连接起两个类之间的关系,从而避免不必要的资源浪费。 这是目前被认为是最优解之一的做法[^2]。 ```javascript function inheritPrototype(subClass, superClass) { const prototype = Object.create(superClass.prototype); prototype.constructor = subClass; subClass.prototype = prototype; } inheritPrototype(Child, Parent); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值