本章题目是继承,实质上介绍JS如何实现面向对象的三大特性,封装,继承,多态。本章的最后一个小节介绍事件。

  与Java语言对比,虽然名称同样称为类,对象,但是显然它们的含义存在一些细微的差异,而且实现三大特性的方式存在很大差异。所以用Java的概念去理解JS中的面向对象反而会很困惑。

  从实际效果看,JS同样可以实现复杂的类结构,例如easyui中存在工具类(parser,loader),接口(resizable,draggable,droppable),继承(validatebox,textbox,maskedbox),组合(datebox是由textbox,calendar)等,分析这些组件之间的关系已不那么简单。所以JS还是很强大的。

  个人感觉本章的重点是理解JS的继承概念是对象与对象之间的继承,区别Java语言中类与类之间的继承。

  原文总共包含六个小节,结构如下:

  1. 第一小节介绍继承的概念以及JS语言实现继承的概念。
  2. 第二小节介绍虚伪的继承,并演示继承的示例。
  3. 第三小节介绍将多个参数封装为对象,这里的参数更偏向于构造器的参数,这些参数将作为类的实例成员。
  4. 第四小节介绍通过原型链实现继承
  5. 第五小节介绍通过函数私有变量实现封装
  6. 第六小节介绍事件。

1、继承概念

本小节总共分为五段,

第一段为一句话,阐述继承在面向对象语言中的重要性。

第二段阐述继承的优点

  1. 代码复用,子类可以直接使用父类中继承得到的属性和方法。
  2. 继承是实现复杂类结构的重要手段,父类与之类存在泛化关系。

第三段阐述的是类转换,在Java语言或其他面向对象语言中,父类与子类之间的转换,当需要父类时,子类可以自动转换为父类;当需要子类时,父类必须强转换为子类。而在JS中不存在这种类型转换。

第四段阐述的是JS语言的面向对象特性不比其他语言差。

第五段阐述的是JS实现继承的机制,理解这段话很重要。

  在Java语言中,继承通常发生在类与类之间,而在JS语言,继承发生在对象与对象之间。类是一组公共事物的抽象,它并不存在,实际上是一个概念,例如大学,人。对象是现实事物的一个抽象,它反应实际存在的事物,例如北京大学,张三。类与对象之间的关系,是抽象到具体的关系。

  Java语言中继承发生在类与类之间,医生,律师,工人,农民,官员继承人,它的角度是工作的职责,父亲,母亲,孩子,兄弟继承人,它的角度是家庭的关系。而对象张三可以是工人,在第二种角度中,它可以是父亲,孩子,兄弟等等,角色可以是互斥的,也可以是同时存在的,但是所有的这些都是更全面认识对象张三的抽象概念,如果角度更多,认识张三也更全面,但是对象是同一个。

  在JS语言中继承是发生在对象与对象之间,假设这里类是人,对象是张三,李四,王五等等,张三继承李四,在初次接触时,疑惑很多,想不通。随着JS语言的经验增加,理解对象与对象之间概念更偏向于模板与实物之间的关系,两者都是同时存在的。举个简单的示例,月饼的模板与月饼之间的关系,可以看出月饼模板的作用就是为了产生月饼,它并没有其他的用途。对比构造器与new创建的对象之间的关系,构造器的用途就是为了产生这类对象,构造器自身确实也可以调用,也可以被当做函数独立存在,但是它是没有意义的。

父对象与子对象之间的关系,产生父对象只是为了更方便的产生子类对象,父对象是子对象的模板。

2、继承的实现

拥有相同原型链的对象为同类。可以理解为调用Object.getPrototypeOf返回相同对象的实例为同类。

在继续之前,需要理解prototype属性,原型链,以及对象自身三者的关系。

假设将原型链理解为月饼模板,而对象理解为月饼。那么创建对象的一般步骤如下。

  1. 首先创建一个月饼模板,或者利用已经存在的月饼模板。本质是创建一个原型链对象,这个对象是什么样并不知道,但是它不能是基本数据类型,例如字符串,数字,布尔等。
  2. 完善这个模板,可以理解为给原型链对象添加方法和属性。
  3. 建立月饼模板与月饼之间的关系,可以理解为原型链对象必须与新对象存在原型链关系,之前它们只是两个独立的对象而已。
// 创建模板对象
var templateObj = {};
// 这样新建立的对象会与模板对象之间产生原型链关系
var obj = Object.create(templateObj);
// 给模板对象添加方法
templateObj.hello = function(){
console.log("Hello "+ this.name);
}
// 新对象属性
obj.name = "张三";
// 调用模板中的方法
obj.hello();

  在创建对象的关键在于建立模板对象与对象的原型链关系,这种方式有两种,一种是Object.create(templateObj),另外一种方式是构造器function Templateobj();推荐使用构造器方式,上述示例只是为了演示继承关系。对于模板对象,是没有任何限制的,它可以是Function,Object,亦或者其他任何对象。

3、封装参数

  当使用构造器方式创建对象时,如果需要传入很多参数,可以将其封装为对象,具体可以参考任意UI组件的options对象,在编写时必须考虑参数是否必填,不是必填情况下必须设置合适的默认值,防止出现错误。例如在easyui的datagird组件,columns列肯定是必填的,很多其他配置项都有默认值。

4、构造器方式

  在第二小节中已经演示了如何使用原型链实现继承,在原书中第二小节演示如何使用构造器实现继承。

  构造器实现继承比较简单。

// 同时prototype属性,
// 该属性值为一个对象,它拥有constructor属性,属性值为TemplateObj, TemplateObj.prototype = {constructor:TemplateObj}
// 并将该对象作为new出来对象的原型链对象。
function TemplateObj(name) {
this.name = name;
}
// 完善模板,添加一些方法
TemplateObj.prototype.hello = function () {
console.log("Hello " + this.name);
};
// 绑定新对象与模板对象之间的原型链关系,此时Object.getPrototypeOf(obj) === TemplateObj.prototype
var obj = new TemplateObj("张三");
obj.hello();

5、封装

  封装的实现利用的是函数的私有作用域。实现封装的步骤如下

  1. 创建任意函数private,它的作用是提供私有的作用域。
  2. 在函数中定义任意的变量,这些变量为对象的私有属性。
  3. 在函数中创建对象,并将该对象返回,该对象包含所有的公共属性。
function Person(name) {
// 私有属性
var age = 21;
// 私有属性
var country = "中国";
// 公共属性
var hello = function () {
console.log("Hello " + this.name + "年龄为:" + age + "国家为:" + country);
};
// 创建新对象
var person = {
name:name,
hello: hello
};
return person;
}

6、事件

  事件的三个主要过程是注册事件,触发事件,关联的事件处理器运行。本小节中引用原书的例子,其中触发事件的操作只能是主动去调用本例中的fire方法。

// 给对象添加事件相关的方法
var eventuality = function (that) {
// 注册事件的对象,它的key为事件的类型,为字符串
// 它的value为事件处理器数组,每个数组中都包含一个handler对象,
// 每个handler都拥有两个属性,method:处理器方法;parameters:处理器方法的参数
var registry = {};
// 注册事件,第一个参数为事件类型,第二个参数为处理器方法,第三个参数为处理器的参数
// 当事件已存在时,将处理器方法和参数构成新对象handler,添加到数组当中
// 当事件不存在时,key = type; value = [handler];
that.on = function (type, method, parameters) {
var handler = {
method: method,
parameters: parameters
};
if (registry.hasOwnProperty(type)) {
registry[type].push(handler);
} else {
registry[type] = [handler];
}
return this;
};
// 触发事件,本质上是根据事件的类型找到对应的处理器数组,循环数组,运行其中的方法
that.fire = function (event) {
var array; // 临时保存事件对应的处理器数组,包含一个个handler对象
var func; // 临时保存handler对象中的处理器方法
var handler; // 临时保存处理器对象
var i; // 循环变量i
// 临时保存处理器方法的参数,当handler的参数属性为空时,将event作为参数
var type = typeof event === "string" ? event : event.type;
// 循环执行
if (registry.hasOwnProperty(type)) {
array = registry[type];
for (i = 0; i < array.length; i++) {
handler = array[i];
func = handler.method;
if (typeof func === "string") {
func = this[func];
}
func.call(this, handler.parameters || [event]);
}
}
return this;
};
return that;
};

前端——语言——Core JS——《The good part》读书笔记——第五章节(Inheritance)的更多相关文章

  1. 前端——语言——Core JS——《The good part》读书笔记——初篇

    本书是一本经典,优秀的JS书籍. 目的 在书籍中作者多次提及本书的目的,让读者去发现语言中的精华部分,避免糟粕部分,提高代码的编写质量.简述为取其精华去其糟粕. 本书的内容只涉及到Core JS部分, ...

  2. 前端——语言——Core JS——《The good part》读书笔记——第四章节(Function)

    本章介绍Function对象,它是JS语言最复杂的内容. Java语言中没有Function对象,而是普通的方法,它的概念也比较简单,包含方法的重载,重写,方法签名,形参,实参等. JS语言中的Fun ...

  3. 前端——语言——Core JS——《The good part》读书笔记——第九,十章节(Style,Good Features)

    第九章节 本章节不再介绍知识点,而是作者在提倡大家培养良好的编码习惯,使用Good parts of JS,避免Bad parts of JS.它是一篇文章. 本文的1-3段阐述应用在开发过程中总会遇 ...

  4. 前端——语言——Core JS——《The good part》读书笔记——第一章节(Good Parts)

    本章是引言,有四个小节,具体内容如下: 第一小节 第一小节介绍作者的观点,作者编写本书的目的. 原文:I discovered that I could be a better programmer ...

  5. 前端——语言——Core JS——《The good part》读书笔记——第七章节(正则)

    本章介绍正则表达式的内容.正则表达式是一门独立的语言,它拥有自己的语法规则,在学习本章之前需要了解基本的语法规则. 正则表达式是通用的,意味着同样的语法规则可以适用于不同的编程语言,相同的正则表达式在 ...

  6. 前端——语言——Core JS——《The good part》读书笔记——第三章节(Object)

    本章介绍对象. 在学习Java时,对象理解为公共事物的抽象,实例为具体的个例,对象为抽象的概念,例如人为抽象的概念,具体的个例为张三,李四. Java对象种类多,包含普通类,JavaBean,注解,枚 ...

  7. 前端——语言——Core JS——《The good part》读书笔记——第六章节(Arrays)

    本章介绍数组的内容,Java中的数组在创建时,会分配同等大小的内存空间,一旦创建数组的大小无法改变,如果数据超过数组大小,会进行扩容操作.并且数组的元素类型在创建时必须是已知的,而且只能存放相同数据类 ...

  8. 前端——语言——Core JS——《The good part》读书笔记——第八章节(Methods)

    本章介绍JS核心对象的方法.这些对象包括Array,Function,Number,Object,RegExp,String.除这些常用的核心对象还有Date,JSON. 本章更偏向于API文档,介绍 ...

  9. 前端——语言——Core JS——《The good part》读书笔记——附录三,四,五(JSLint,铁路图,JSON)

    1.JSLint 本书的JSLint部分只是一个引言,详细了解该工具的使用参考http://www.jslint.com/ 2.铁路图 在本书中使用过的铁路图集中放在这部分附录中,其实读完本书之后,没 ...

随机推荐

  1. URLSearchParams/FormData

    一.URLSearchParams()(很好用,但有一定兼容问题,未来版本的浏览器中该功能的语法和行为可能随对应的标准文档而改变.) URLSearchParams 接口定义了一些实用的方法来处理 U ...

  2. [CF1034B] Longest Palindrome - 贪心

    如果自己是回文串可以做中心 如果一个串和另一个串的转置相等则可以凑一对 优先配对 #include <bits/stdc++.h> using namespace std; int n,m ...

  3. Springboot 中的配置文件

    Spring Boot提供了两种常用的配置文件,分别是properties文件和yml文件.他们的作用都是修改Spring Boot自动配置的默认值. 技术:yaml.properties语法,Con ...

  4. WebService 之 SoapHeader

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  5. python面试的100题(18)

    函数 52.python常见的列表推导式? 列表推导式书写形式: [表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件] 参考地址:https://www.cnb ...

  6. 字符串匹配算法--KMP字符串搜索(Knuth–Morris–Pratt string-searching)C语言实现与讲解

    一.前言   在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置.此算法通过运用对这个词在不匹配时本身就包含足够的信息 ...

  7. 少年的u

    发现了我提取DNa的过程存在问题,能够跑出action 但是不能克隆出基因.老师给我解释了为什么,说是我的DNA质量不是很高.但是在接下来的时间我会解决这个问题. 和师姐一起去上面的实验室,看了定量P ...

  8. Codeforces Round #603 (Div. 2) C.Everyone is A Winner!

    tag里有二分,非常的神奇,我用暴力做的,等下去看看二分的题解 但是那个数组的大小是我瞎开的,但是居然没有问题233 #include <cstdio> #include <cmat ...

  9. Centos7在防火墙中添加访问端口

    1.       查看jenkins启动状态命令:systemctl status Jenkins 保证jenkins启动,此处的状态为正在运行 2.       查看防火墙状态命令:systemct ...

  10. k线中转器

    自动同步服务器k线,将交易日k线存入共享内存,交易平台直接去共享内存取想要的数据. 默认提供期货1.3.5分钟.日线数据.如果想要自定义,可以通过copydata向它发送请求,可以提供任何周期,任何偏 ...