资讯专栏INFORMATION COLUMN

JavaScript 继承

Guakin_Huang / 697人阅读

摘要:继承一共有三种方式类式继承原型式继承掺元类类式继承可以被装扮成使用类式继承的语言。在使用原型式继承时,不需要用类来定义对象的结构,只需直接创建一个对象即可。原型式继承更能节约内存。

今天整理面试题的时候看见一道题叫讲一下继承,虽然继承以前也看过书,也在用,但是居然无法总结性、系统地回答这个问题,于是赶紧把《JavaScript设计模式》扒拉出来看看。

为什么需要继承

在设计类的时候,能够减少重复性代码,并且能尽量弱化对象间的耦合。可以在现有类的基础上进行设计并充分利用已经具备的各种方法,而对设计的修改也更为轻松。
继承一共有三种方式:类式继承、原型式继承、掺元类

类式继承

JavaScript可以被装扮成使用类式继承的语言。通过用函数来声明类、用关键字 new 来创建实例,JavaScript中的对象也能模仿Java或C++中的对象。
首先创造一个简单的类声明,及对该类的实例化:

// 创建 Person 类
function Person (name) {
    this.name = name;
}

Person.prototype.getName = function () {
    return this.name;
};

// 实例化 Person 类
var reader = new Person ("John Smith");
reader.getName();   // John Smith

创建继承 Person 的类 Author :

// 创建继承 Person 的类 Author
function Author (name,books) {
    Person.call(this,name);
    this.book = books;
}

// 派生子类
Author.prototype = new Person();
Author.prototype.constructor = Author;
Author.prootype.getBooks = function () {
    return this.book;
};

在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性是一个指向 prototype 属性所在函数的指针。
为了简化类的声明。可以把派生子类的整个过程包装在一个名为 extend 的函数中,作用是基于一个给定的类结构创建一个新的类。

// extend 函数
function extend(subClass,superClass) {
    var F = function() {};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
    
    // 确保超类的 constructor 属性被设置正确
    subClass.superclass = superClass.prototype;
    if(superClass.prototype.constructor == Object.prototype.constructor) {
        superClass.prototype.constructor = superClass;
    }
}

那么 Author 的继承可以改写为:

function Author (name,books) {
    Author.superClass.contructor.call(this,name);
    this.books = books;
}
extend(Author,Person);   // 调用 extend 函数

Author.prootype.getBooks = function () {
    return this.book;
};
原型式继承

原型式继承和类式继承截然不同。在学习原型式继承时,最好忘掉自己关于类和实例的一切知识,只从对象的角度来考虑。
在使用原型式继承时,不需要用类来定义对象的结构,只需直接创建一个对象即可。这个对象随后可以被新的对象重用,这得益于原型链查找的工作机制,该对象被称为原型对象。
下面使用原型式继承来重新设计 Person 和 Author

// Person 原型对象
var Person = {
    name: "default name",
    getName: function() {
        return this.name;
    }
};

Person 现在是一个对象字面量,其中定义了所有类 Person 对象都要具备的属性和方法,并为他们提供了默认值。clone 函数可以用来创建新的类 Person 对象,该函数会创建一个空对象,而该对象的原型对象被设置为 Person。

// Author 原型对象
var Author = clone(Person);
Author.books = [];   // Default value
Author.getBooks = function () {
    return this.books;
};

一个克隆并非原型对象的一份完全独立的副本,它只是一个以那个对象为原型对象的空对象。对继承而来的成员有读和写的不对等性:

var authorClone = clone(Author);
alert(authorClone.name);   // default name (连接到 Person.name)
authorClone.name = "new name";
alert(authorClone.name);   // new name (连接到 authorClone.name)

authorClone.books.push("new book");   // 在这里,想authorClone.books数组添加
                                      // 新元素实际上是把这个元素添加到
                                      // Author.books数组中。
authorClone.books = [];
authorClone.books.push("new book");                                

这也就说明了为什么必须为通过引用传递的数据类型的属性创建新的副本。在以上例子中,向authorClone.books数组添加新元素实际上是把这个元素添加到Author.books数组中。这可不是什么好事,因为对那个值的修改不仅会影响到 Author,而且会影响到所有机场了Author但还未改写那个属性的默认值的对象。在改变所有那些数组和对象的成员之前,必须先为其创建新的副本。

类似继承和原型式继承的对比

包括JavaScript程序员在内的整个程序员群体对类式继承都比较熟悉。
原型式继承更能节约内存。在原型链中查找成员的方式使得所有克隆出来的对象都共享每个属性和唯一一份实例,只有在直接设置了某个克隆出来的对象的属性和方法时,情况才会有所变化。而类似继承方式中创建的每一个对象在内存中都有自己的一套属性的副本。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90936.html

相关文章

  • 彻底搞懂JavaScript中的继承

    摘要:这正是我们想要的太棒了毫不意外的,这种继承的方式被称为构造函数继承,在中是一种关键的实现的继承方法,相信你已经很好的掌握了。 你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- 继承就和原型链这一概念息息相关。甚至可以说,所谓的原型链就是一条继承链。有些困惑了吗?接着看下去吧。 一、构造函数,原型属性与实例对象 要搞清楚如何在JavaScript中实现继承,...

    _ivan 评论0 收藏0
  • 讲清楚之 javascript 对象继承

    摘要:中的继承并不是明确规定的,而是通过模仿实现的。继承中的继承又称模拟类继承。将函数抽离到全局对象中,函数内部直接通过作用域链查找函数。这种范式编程是基于作用域链,与前面讲的继承是基于原型链的本质区别是属性查找方式的不同。 这一节梳理对象的继承。 我们主要使用继承来实现代码的抽象和代码的复用,在应用层实现功能的封装。 javascript 的对象继承方式真的是百花齐放,属性继承、原型继承、...

    Jonathan Shieber 评论0 收藏0
  • javascript继承 --- 多种继承方式解析(ES5)

    摘要:继承前言作为一门轻量级的脚本语言在和的横空出世之后将其推向的新的高度虽然中出现的新的生成对象的类语法格式但依然为的语法糖而我们依然有必要从的原生实现入手来了解它的继承实现方式给出了更加简洁的固定的类声明方式有兴趣的可以查看阮一峰的入门下面给 javascript继承 前言 javascript作为一门轻量级的脚本语言在ES6和node.js的横空出世之后将其推向的新的高度,虽然 ES6...

    yankeys 评论0 收藏0
  • 白话解释 Javascript 原型继承(prototype inheritance)

    摘要:我们有了构造函数之后,第二步开始使用它构造一个函数。来个例子这种方式很简单也很直接,你在构造函数的原型上定义方法,那么用该构造函数实例化出来的对象都可以通过原型继承链访问到定义在构造函数原型上的方法。 来源: 个人博客 白话解释 Javascript 原型继承(prototype inheritance) 什么是继承? 学过面向对象的同学们是否还记得,老师整天挂在嘴边的面向对象三大特...

    kid143 评论0 收藏0
  • javascript继承你了解多少?

    摘要:和构造函数前面提到,是个内置隐藏属性,虽然在可以通过访问,但是其设计本意是不可被读取和修改的,那么我们如何利用原型链来建立继承关系提供了关键字。到这儿,思路就清晰了,怎么让对象和对象的相连实现继承只需把的构造函数的连接到就行了。 什么是继承? 大多数人使用继承不外乎是为了获得这两点好处,代码的抽象和代码的复用。代码的抽象就不用说了,交通工具和汽车这类的例子数不胜数,在传统的OO语言中(...

    baishancloud 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<