一、原型继承
1、原型链继承:全量继承,无法实现部分继承
缺点:继承了过多不必要的属性
// 父级
Professor.prototype = {
name: 'Zhang',
tSkill: 'JAVA'
}
function Professor() {}
var professor = new Professor();
// -------------分割线----------
// 子级
Teacher.prototype = professor;
function Teacher() {
this.name = 'Wang',
this.mSkill = 'JS'
}
var teacher = new Teacher();
// -------------分割线----------
// 孙子级
Student.prototype = teacher;
function Student() {
this.name = 'Li',
this.pSkill = 'HTML'
}
var student = new Student();
console.log(student);
2、借助 call/apply 实现继承: 只能借用属性和方法,无法继承原型
缺点:无法继承借用构造函数的原型
Teacher.prototype.wife = 'Liu';
function Teacher(name, mSkill) {
this.name = name;
this.mSkill = mSkill;
}
function Student(name, mSkill, age, major) {
Teacher.apply(this, [name, mSkill]);
this.age = age;
this.major = major;
}
var student = new Student('Zhang', 'JS', 18, 'Computer');
console.log(student);
3、公共原型继承
缺点:两个原型会相互影响,更改其中一个原型,更一个对应的原型也会被更改。
function Teacher() {
this.name = 'Li';
this.tSkill = 'Java';
}
Teacher.prototype = {
pSkill: 'JS'
}
var t = new Teacher();
console.log(t);
function Student() {
this.name = 'Wang';
}
Student.prototype = Teacher.prototype;
Student.prototype.age = 18;//Student里面添加属性,Teacher里面的属性也会跟着改变,这样是不行的;
var s = new Student();
console.log(s);
4、企业级继承:圣杯模式
终极解决方案: 加中间缓冲对象,即可解决只继承父级的原型,而不继承构造属性
//父构造函数
function Teacher() {
this.name = 'Li';
this.tSkill = 'Java';
}
Teacher.prototype = {
pSkill: 'JS'
}
var t = new Teacher();
console.log(t);
// 中间对象缓冲
function Buffer() {}
Buffer.prototype = Teacher.prototype;
var buffer = new Buffer();
console.log(buffer);
// 子构造函数
function Student() {
this.name = 'Wang';
}
Student.prototype = buffer;
Student.prototype.age = 18;
//这里的Teacher.prototype并没有直接赋值给Student.prototype,而是赋值给Buffer.prototype
//Buffer的实例化对象赋值给了Student.prototype
//而通过实例化对象是不能修改自己祖先的prototype的属性和方法的!具体例子详见:
//https://mp.weixin.qq.com/s/n25bWS481nHl6sXzwiE93g
//故Student.prototype的修改是不影响Teacher的prototype的
var s = new Student();
console.log(s);
5、圣杯封装
function inherit(Target, Origin) {
function Buffer(){}
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer();
// 还原构造器
Target.prototype.constructor = Target;
// 设置继承源
Target.prototype.super_class = Origin;
}
// 使用
function Teacher() {}
Teacher.prototype.name = "Zhang";
function Student() {}
inherit(Student, Teacher);
var t = new Teacher();
var s = new Student();
console.log(s);
console.log(t);
6、企业级的模块化封装:闭包+圣杯封装
//非立即函数执行版本
function test() {
var Buffer = function () {
}
function inherit(Target, Origin) {
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer();
Target.prototype.constructor = Target;
Target.prototype.super_class = Origin;
}
return inherit
}
var inherit = test()
//立即函数执行版本--->企业级写法--->模块化开发----->防止全局环境污染--->有利于维护
var inherit = (function() {
var Buffer = function() {}
//这里用到的是闭包
return function(Target, Origin) {
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer();
// 还原构造器
Target.prototype.constructor = Target;
// 设置继承源
Target.prototype.super_class = Origin;
}
})();
function Teacher() {}
Teacher.prototype.name = "Zhang";
function Student() {}
inherit(Student, Teacher);
var t = new Teacher();
var s = new Student();
console.log(s);
console.log(t);
7、企业级协同开发:一个简单的示例
var inherit = (function() {
var Buffer = function() {}
return function(Target, Origin) {
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer();
// 还原构造器
Target.prototype.constructor = Target;
// 设置继承源
Target.prototype.super_class = Origin;
}
})();
//如果没有"var initPrammer =",那么这个函数就会立即执行
//有了"var initPrammer =",等式右边就会等待着去执行
var initPrammer = (function(){
var Programmer = function(){}
Programmer.prototype = {
name: '程序员',
tool: '计算机',
work: '编写应用程序',
say: function(){
console.log(this.myName + this.name + ',' + this.tool + this.work + ',' + this.lang.toString());
}
}
function FrontEnd(){}
function BackEnd(){}
inherit(FrontEnd, Programmer);
inherit(BackEnd, Programmer);
FrontEnd.prototype.lang = ['HTML', 'CSS'];
FrontEnd.prototype.myName = '前端';
BackEnd.prototype.lang = ['JAVA', 'PHP'];
BackEnd.prototype.myName = '后端';
return {
FrontEnd: FrontEnd,
BackEnd: BackEnd
}
})();
var frontEnd = new initPrammer.FrontEnd();
frontEnd.say();
var backEnd = new initPrammer.BackEnd();
backEnd.say();
原文始发于微信公众号(迪哥讲事):JS基本功系列-原型链中的一种模块化开发定式: 圣杯模式
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论