博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js 继承小结
阅读量:6038 次
发布时间:2019-06-20

本文共 2516 字,大约阅读时间需要 8 分钟。

js的是利用原型链实现面向对象的类行为,和oo语言中的类有这巨大的不同。

下面讲述几种继承的方式以及一些扩展。

我对js的原型继承的一些理解:

  • js中只有函数存在prototype这个属性,代表原型,object中只有__proto__属性
  • js中函数也是object的一种,所以函数同时存在prototype和__proto__属性,但是这是两个完全不同的属性
  • js中所有的object都是继承于底层的Object.prototype
  • js中所有函数的构造函数是Function
  • Function.prototype是函数(这就是解决原型链循环的关键),正常函数的prototype属性都是一个object
  • js中实例的__proto__总是指向它构造函数的prototype(这个也是原型链的重点)
// 父类function Animal() {  this.name = 'animal';  this.type = 'animal';}Animal.prototype.say = function () {  console.log(this.name);}复制代码

原型链继承, 通过子类的prototype是父类的一个实例,从而实现一条原型链,如下:(Sub代表子类,sub代表子类的一个实例,Super代表父类,super代表父类的实例)

sub.__proto__ = Sub.prototype = super, super.__proto__ = Super.prototype复制代码

缺点:父类的数据对象处于子类的prototype中,prototype是所有子类实例所共有的,所以对于引用类型的数据存在一改全改的问题

function Dog() {  this.name = 'dog'}Dog.prototype = new Animal();var dog = new Dog();dog.say();复制代码

dog的详细结构

为了解决上面的原型链缺点,利用构造函数的优点(组合继承)

function Cat(data) {  Animal.call(this, data); // 将父类的数据类型在子类复制一份  this.name = 'cat';}Cat.prototype = new Animal();var cat = new Cat(); // 构造函数再次存储了一份父类的数据类型cat.say();复制代码

cat详细结构,可以发现有个缺点就是父类的数据类型被存储了2遍

ES5中有个api:

Object.create(object1, object2): 返回一个object,object的prototype = object1,object2代表prototype中新增或者覆盖的属性eg:var cat = Object.create(new Animal(), {    name: {        value: 'cat'    }})复制代码

上述cat详细结构

参考红宝书(js高级程序设计):这种方式称为原型式继承

function object(o) {    function F(){}    F.prototype = o;    return new F();}复制代码

结合原型式继承和构造函数,可以有如下的继承方式

function Bird(data) {  Animal.call(this, data);  this.name = 'bird';}Bird.prototype = Object.create(Animal.prototype);Bird.prototype.constructor = Bird;var bird = new Bird();bird.say();复制代码

bird的详细结构:解决了原型链继承和组合继承的问题

构造函数有个特点,就是return的是一个对象的时候new的时候生成的就是这个对象,否则将按照正常的原型链生成对象。eg:

function Test() {    var arr = [1, 2, 3];    this.arr = arr;    return arr;}Test.prototype.say = function() {    console.log(this.arr);}var test = new Test();test.say // undefined复制代码

这就是传说中的寄生继承,寄生继承返回的对象跟原型链基本保持一致,唯一的问题就是丢失了子类的构造函数吧,以及第一层prototype

function Horse() {  var o = Object.create(new Animal());  o.name = 'horse';  return o;}var horse = new Horse();horse.say();复制代码

horse详细结构:

扩展题目: 如何继承数组?

// 实现数组继承var push = [].push;function myArray() {  var array = Array.apply(this, arguments);  array.__proto__ = myArray.prototype;  return array;}myArray.prototype = Object.create(Array.prototype)myArray.prototype.constructor = myArray;myArray.prototype.push = function(value) {  console.log('push:', value);  push.call(this, value);}var list = new myArray(1, 2, 3);list.push(4);复制代码

因为数组的独特性所以利用了寄生继承以及object的__proto__属性,以及原型式继承

转载地址:http://znlhx.baihongyu.com/

你可能感兴趣的文章
设计模式之---工厂方法
查看>>
怎么样能把视频里的音乐提取出来?
查看>>
2013年4月MVP开始申请了【截止时间:1月13日】
查看>>
网站出现502 BAD GATEWAY的解决办法
查看>>
linux umount共享盘
查看>>
办理生育服务证、再生一胎生育证办理指导
查看>>
我的友情链接
查看>>
一个比较高级的脚本示例
查看>>
Swift学习笔记_数据类型_浮点类型
查看>>
Http Get 从服务器中获取数据 存储到本地
查看>>
gdbserver调试共享库(一)
查看>>
mmm_agent_navy2.conf is world readable! at /usr/share/perl5/MMM/Common/Config.pm line 132
查看>>
ruby1.9.1 watir
查看>>
我的友情链接
查看>>
文件系统
查看>>
安装scp命令
查看>>
使用PowerShell管理Hyper-v
查看>>
最近在读的书
查看>>
phpmyadmin登录后显示“phpMyAdmin 高级功能尚未完全设置,部分功能未激活。查找原因...。”错误提示...
查看>>
JAVA实现NIO非阻塞TCP通信--客户端
查看>>