1.原型链继承
核心: 将父类的实例作为子类的原型
将构造函数的原型设置为另一个构造函数的实例对象,这样就可以继承另一个原型对象的所有属性和方法,可以继续往上,最终形成原型链
父类

// 定义一个动物类
function Animal (name) {// 属性this.name = name || 'Animal';// 实例方法this.sleep = function(){console.log(this.name + '正在睡觉!');}
}
// 原型方法
Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

问题
1.来自原型对象的所有属性被所有实例共享
2.创建子类实例时,无法向父类构造函数传参

2.构造函数继承
使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

function SuperType() {this.colors = ["red", "blue", "green"];
}function SubType() {//继承SuperTypeSuperType.call(this);
}var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"

特点:
解决了1中,子类实例共享父类引用属性的问题
创建子类实例时,可以向父类传递参数
可以实现多继承(call多个父类对象)
缺点:
实例并不是父类的实例,只是子类的实例
只能继承父类的实例属性和方法,不能继承原型属性/方法
无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

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.constructor = SubType;
SubType.prototype.sayAge = function() {alert(this.age);
};var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27 

将SubType的原型指定为SuperType的一个实例,大致步骤和原型链继承类似,只是多了在SubType中借调SuperType的过程。
实例属性定义在构造函数中,而方法则定义在构造函数的新原型中,同时将新原型的constructor指向构造函数。
可以通过instanceof和isPrototypeOf()来识别基于组合继承创建的对象。
避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为JS中最常用的继承模式。

4.原型式继承
不自定义类型的情况下,临时创建一个构造函数,借助已有的对象作为临时构造函数的原型,然后在此基础实例化对象,并返回。

function object(o){function F(){}F.prototype = o;return new F();
}

本质上是object()对传入其中的对象执行了一次浅复制

var person = {name: "Nicholas",friends: ["Shelby", "Court", "Van"]
};var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"

原型的引用类型属性会在各实例之间共享。
当只想单纯地让一个对象与另一个对象保持类似的情况下,原型式继承是完全可以胜任的。

5.寄生组合式继承
组合继承是JS中最常用的继承模式,但其实它也有不足,组合继承无论什么情况下都会调用两次超类型的构造函数,并且创建的每个实例中都要屏蔽超类型对象的所有实例属性。
寄生组合式继承就解决了上述问题,被认为是最理想的继承范式。

function object(o) {function F(){}F.prototype = o;return new F();
}function inheritPrototype(superType, subType) {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(SuperType, SubType);   // 这一句,替代了组合继承中的SubType.prototype = new SuperType()SubType.prototype.sayAge = function() {alert(this.age);
};

不必为了指定子类型的原型而调用超类型的构造函数,我们需要的只不过是超类型原型的一个副本
在inheritPrototype()函数中所做的事:

1.在inheritPrototype函数中用到了原型式继承中的object()方法,将超类型的原型指定为一个临时的空构造函数的原型,并返回构造函数的实例。

2.此时由于构造函数内部为空(不像SuperType里面有实例属性),所以返回的实例也不会自带实例属性,这很重要!因为后面用它作为SubType的原型时,就不会产生无用的原型属性了,借调构造函数也就不用进行所谓的“重写”了。

3.然后为这个对象重新指定constructor为SubType,并将其赋值给SubType的原型。这样,就达到了将超类型构造函数的实例作为子类型原型的目的,同时没有一些从SuperType继承过来的无用原型属性。

本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。

欢迎一起私信交流。

“睡服“面试官系列之各系列目录汇总(建议学习收藏)

“约见”面试官系列之常见面试题第三十八篇之js常见的继承方式(建议收藏)相关推荐

  1. “约见”面试官系列之常见面试题第三十九篇之异步更新队列-$nextTick(建议收藏)

    目录 一,前言 二,什么是异步更新队列 三,使用异步更新队列 四,结尾 一,前言 这一篇介绍有关异步更新队列的知识,通过异步更新队列的学习和研究能够更好的理解Vue的更新机制 二,什么是异步更新队列 ...

  2. “约见”面试官系列之常见面试题之第九十五篇之vue-router的组件组成(建议收藏)

    <router-link :to='' class='active-class'> //路由声明式跳转 ,active-class是标签被点击时的样式<router-view> ...

  3. “约见”面试官系列之常见面试题之第九十二篇之created和mounted区别(建议收藏)

    beforeCreate 创建之前:已经完成了 初始化事件和生命周期 created 创建完成:已经完成了 初始化注册和响应 beforeMount 挂载之前:已经完成了模板渲染 mounted :挂 ...

  4. “约见”面试官系列之常见面试题第四十二篇之原型和原型链(建议收藏)

    原型和原型链的理解:(面试题) 原型:每个函数都有 prototype 属性,该属性指向原型对象:使用原型对象的好处是所有对象实例共享它所包含的属性和方法. 原型链:主要解决了继承的问题:每个对象都拥 ...

  5. “约见”面试官系列之常见面试题第三十六篇之CSS常见兼容性问题及解决方案(建议收藏)

    CSS常见兼容性问题及解决方案: 1. 上下margin重合问题: 问题描述:相邻的margin-left和margin-right是不会重合的,但是相邻的块级元素margin-top 和margin ...

  6. “约见”面试官系列之常见面试题之第九十九篇之router的钩子函数(建议收藏)

    当使用路由参数时,例如从 /user/aside导航到 /user/foo,原来的组件实例会被复用.因为两个路由都渲染同个组件,比起销毁再创建,复用则更加高效.不过,这也意味着组件的生命周期钩子不会再 ...

  7. “约见”面试官系列之常见面试题之第六十七篇之jsonp原理和实现(建议收藏)

    一. 同源策略 所有支持Javascript的浏览器都会使用同源策略这个安全策略.看看百度的解释: 同源策略,它是由Netscape提出的一个著名的安全策略. 现在所有支持JavaScript 的浏览 ...

  8. “约见”面试官系列之常见面试题之第六十三篇之get和post区别(建议收藏)

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

  9. “约见”面试官系列之常见面试题之第五十三篇之网站的资源优化(建议收藏)

    本面试题为前端常考面试题,后续有机会继续完善.我是歌谣,一个沉迷于故事的讲述者. 欢迎一起私信交流. "睡服"面试官系列之各系列目录汇总(建议学习收藏)

最新文章

  1. kotlin设置CORS跨域资源共享,java设置允许跨域,服务端如何设置 springboot中设置跨域资源共享
  2. 最新组合式模型量化方法,实现FPGA最高硬件利用率,准确率-推理速度达到SOTA...
  3. Visual Studio 2008 每日提示(二十三)
  4. 如何循序渐进向DotNet架构师发展
  5. leetcode 220. Contains Duplicate III | 220. 存在重复元素 III (Treeset解法+分桶解法)
  6. 决策树的选择,哪个放在第一个需要决策的环节
  7. Map.Entry如何使用?
  8. GPU+Cuda8.0+cudnn8+OpenCv2.4.13+Caffee 安装教程嘎嘎
  9. java爬虫12306_java爬虫12306,爬取所有的站点和车次,并导入postgreSQL数据库
  10. QT视频采集之编码Enc和录像Rec
  11. KMS知识文档管理系统如何与BPM流程管理相结合
  12. 2020找工作更难了?做好这4方面,找到高薪好工作
  13. 大数据开发:基于Hadoop的数据分析平台
  14. html word 编辑表格,在Word文档中运用编辑表格的7个技巧
  15. mercury路由器重置后服务器无响应,MERCURY无线路由器重置后重新设置不能 – 手机爱问...
  16. 002稀疏数组和队列[超大章]
  17. 几行代码!用 Python 画漂亮、专业的插图
  18. 【opencv】高频低频滤波
  19. Jabber 技 术 概 况
  20. Socket基础八:网络IO模型的应用

热门文章

  1. TAppEncoder的main函数
  2. HandlerThread用法
  3. PHP-递归扫描目录和删除目录
  4. CSS3 动画 思维导图
  5. 清除浮动造成的影响的解决方案总结
  6. 在FF与IE中使用数据岛
  7. php访问者信息,如何通过PHP检索访问者的ISP?
  8. python测试字符串类型的函数_python-02 数据类型 字符串str
  9. 尼康d850相机参数测试软件,尼康 - D850 - 产品介绍
  10. 78oa mysql_78oa系统版本升级方法