Javascript作为一门脚本语言,在设计之初并没有考虑到面向对象的特性。即便到了当今这个遍布现代浏览器的年代,各种Javascript 框架/库如雨后春笋般地疯狂生长,Javascript中连个 class 关键字都没有。如果你要编写一个类,你还得借助于function,至于继承、重载什么的,就别奢望了。
可是,没有继承,日子怎么过啊?难道把所有的共有逻辑都拷贝一遍,实现最低级的代码复用?
答案当然是——NO,所以,我们要自己实现继承!
目标
最关键的目标当然是继承——子类自动拥有父类的所有公共属性和方法。
支持instanceof,例如c是子类的实例,而P是父类,c instanceof P应该返回true。
其次应该能够重写(Override)父类的方法,并且在子类的方法中,能够方便地调用到父类的同名方法。
至于说重载(Overload),由于Javascript的语言特性(不可以有同名方法,即便它们参数列表不一样),无法实现。
设计与实现
Javascript的对象有一个很重要的属性——__proto__,也就是原型。原型实质上也是一个对象,所有它也可以有自己的原型,这样就形成一个原型链。当你调用某个对象的某个方法,或者读取该对象的某个属性,Javascript执行器是这样做的:
1、首先到该对象中找对应的方法或属性,如果找不到,
2、到该对象的原型中找,如果还找不到,
3、到原型的原型里面找
4、...
5、直到最后找到Object的原型为止,如果还没有则返回undefined
如下图所示:
原型链的这个特性,和继承很相似,所以自然而然,我们可以利用它来实现继承机制。而原型链对instanceof的支持,使得它成为很好的选择。
我们定义extend函数,这个函数接受两个参数,第一个是父类,第二个是子类,如下所示:
function extend(ParentClass, ChildClass) { ... return ChildClass; }
这个函数对子类进行处理,并返回子类。处理的逻辑如下:
建立原型链
通过将子类的原型链与父类的原型链连接起来,子类可以自动拥有父类的方法和属性:
var pp = ParentClass.prototype, cp = ChildClass.prototype; function T() {}; T.prototype = pp; ChildClass.prototype = new T();
为了连接原型链,需要创建一个父类的实例,并将其赋给子类的原型属性。但我们不希望在extend方法里面就实例化父类,所以引入了一个中间类T,以解决这个问题。
实现重写
原型链建立之后,原来子类原型上的方法和属性我们也需要保留下来:
方法
如果父类有同名方法,我们使用一个闭包,来保留对父类方法和子类方法的引用。然后,修改新的原型中该方法的引用,将其指向一个新的 function。在这个function里面,我们创建一个临时属性super,将其指向父类方法,并调用子类方法,这样在子类方法中,通过 this.super可以调用该父类方法:
ChildClass.prototype[name] = (function(pm, cm) { return function() { var _super = this.super; this.super = pm; var result = cm.apply(this, arguments); this.super = _super; return result; }; })(pp[name], cp[name]);
属性
对于属性,不存在重写的问题,所以直接将子类原来的原型中的属性加到新的原型中即可:
ChildClass.prototype[name] = cp[name];
构造器
为了让子类能够访问到父类的构造器,我们将父类赋给子类的super属性:
ChildClass.super = ParentClass;
如何使用
假设我们要设计一个管理系统,里面涉及到客户、工人和经理等。将客户和员工的共性抽象出来,我们得到人(People);然后将工人和经理的共性抽象得到员工(Employee)。这样我们得到三级类结构:
实现这个设计的代码如下:
function People(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } function Employee(firstname, lastname, company) { Employee.super.apply(this, arguments); this.company = company; } function Manager(firstname, lastname, company, title) { Manager.super.apply(this, arguments); this.title = title; }
我们希望对每个人都有一个描述,People是姓+名;员工在姓+名之后,还包括公司名称;而经理在员工的描述之后,还包括职位。代码如下:
People.prototype.summary = function() { return this.firstname + " " + this.lastname; }; Employee.prototype.summary = function() { return this.super.call(this) + ", " + this.company; }; Manager.prototype.summary = function() { return this.super.call(this) + ", " + this.title; };
在所有的成员方法都已经定义好之后,声明类的继承(必须先定义方法,再声明类的继承,否则无法在方法中使用this.super调用父类方法!):
extend(People, Employee); extend(Employee, Manager);
使用这些类就比较简单,直接new就好了:
var people = new People("Alice", "Dickens"); var employee = new Employee("Bob", "Ray", "Alibaba"); var manager = new Manager("Calvin", "Klein", "Alibaba", "Senior Manager"); console.log( people.summary() ); //Alice Dickens console.log( employee.summary() ); //Bob Ray, Alibaba console.log( manager.summary() ); //Calvin Klein, Alibaba, Senior Manager
这篇文章不错吧,那就给个赞吧!
给大家分享一份我的阿里巴巴的Android面经,整体来看:一面问了一道算法题,还有对项目的细节进行深挖,也注重提问项目框架、架构之类,三轮面试层层深入,挑战性大,一面侧重Java,二面侧重Android,三面问Android更深的源码内容,还有网络这块,大家务必好好准备。 技术题 Java引用类型 Object类里面有哪几种方法 HaspMap扩容机制 equals 和 hashCode方法 ha
面试过程 SQL题目:基于如下数据为电商平台中用户每日订单金额,找出各天订单金额排名前三名的用户,表名temp1。 WITH ref_amt AS ( SELECT dt, user_id, SUM(order_amt) AS order_amt_sum FROM temp1 GROUP BY dt, user_id ) S
双非本科,参加了无数场面试,以下是最近面阿里的总结(来源于网络): 阿里 面经1 简单介绍项目 知道哪些数据结构以及他们的特点 链表增删快,那如何提高其查询效率,有没有什么想法? B+树了解吗?B+树如何范围查询?B+树退化的极端情况是什么? 跳表了解吗? 大顶堆、小顶堆了解吗? 实现长地址请求到服务端,然后服务端重定向短地址给客户端,如何实现长短地址的互相映射? 那我现在有10份数据,有1000
吹爆阿里,整个面试过程体验极佳! 数据库怎么分类,描述一下你对这些数据库的理解 什么情况使用MySQL,什么情况使用Redis Redis有什么持久化策略 MySQL有哪2种引擎,说一下它们的区别 MySQL两个线程的update语句同时处理一条数据,会不会有阻塞 滥用事务,或者一个事务里有特别多sql的弊端 两条update语句处理一张表的不同的主键范围的记录,一个<10,一个>15,会不会遇到
#产品2023笔面经# 去年投简历直接挂 今年投终于收到了笔试 北森题库 40min 10言语理解 10资料分析 10图形推理 51性格测试 形式上和携程、shein的一致,只是性格测评不太一样,求一个面试机会吧
这次是被调岗加面一轮,由于自己的身体状况原因,中间歇了一段时间没有面试,发现距离上次面试已经过去大半个月了。 1.自我介绍 2.介绍一下上段实习主要做什么的,并且进行深挖 3.介绍一下上上段实习是干嘛的,通过什么模型之类的进行工作 4.你觉得你碰到最有挑战的工作是什么 5.为什么投了阿里 6.还投了什么其他公司,并追问为什么没去呢 我:因为没过面试 7.那你觉得面试为什么会没通过 8.读书和工作期
饿了么的数据研发岗位,整体面试体验很好!记录一下我的面(凉)经和反思吧~ 8-9 投递 8-13 行测+性格 8-21 笔试,15选择题,3个编程,我分别是100,90,6 8-25 一面 面试官先自我介绍,然后说大概全程30分钟,然后让我自我介绍。接着问更倾向于做算法还是做开发。有没有大数据,数据开发相关的经验,或者课。 接着问sql常用语句,优化方法。 数据结构相关,排序算法。 手撕代码:两个
双非本科,参加了无数场面试,以下是最近面阿里的总结: 阿里 面经1 简单介绍项目 知道哪些数据结构以及他们的特点 链表增删快,那如何提高其查询效率,有没有什么想法? B+树了解吗?B+树如何范围查询?B+树退化的极端情况是什么? 跳表了解吗? 大顶堆、小顶堆了解吗? 实现长地址请求到服务端,然后服务端重定向短地址给客户端,如何实现长短地址的互相映射? 那我现在有10份数据,有1000个线程来争抢,