继承
伪类
对象说明符
原型
函数化
部件

继承

JS不是基于类的,而是基于原型的,这意味着对象直接从其他对象继承。

1 伪类

JS提供了一套丰富的代码重用模式,它可以模拟那些基于类的模式,因为JS实际上没有类,所以把模拟的类称为伪类。
我们可以定义一个构造器并扩充它的原型:

var Mammal = function (name) {
this.name = name;
};
Mammal.prototype.get_name = function ( ) {
return this.name;
};
Mammal.prototype.says = function ( ) {
return this.saying || '';
};

现在可以构造一个实例:

var myMammal = new Mammal('Herb the Mammal');
var name = myMammal.get_name( ); // 'Herb the Mammal'

可以构造另一个伪类来继承Mammal:

var Cat = function (name) {
this.name = name;
this.saying = 'meow';
};
// 替换Cat.prototype 为一个新的 Mammal 实例
Cat.prototype = new Mammal( );
// 扩充新原型对象,添加purr和get_name方法
Cat.prototype.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
Cat.prototype.get_name = function ( ) {
return this.says( ) + ' ' + this.name +' ' + this.says( );
};
var myCat = new Cat('Henrietta');
var says = myCat.says( ); // 'meow'
var purr = myCat.purr(5); // 'r-r-r-r-r'
var name = myCat.get_name( ); // 'meow Henrietta meow'

2 对象说明符

有时候构造器要接受一大串的参数。这可能是令人烦恼的,因为要记住参数的顺序可能非常困难。例如:

var myObject = maker(f,l,s,c);

不如这么写:

var myObject = maker({
first:f,
last:l,
state:s,
city:c
});

现在多个参数可以按任何顺序排列,如果构造器会聪明地使用默认值,一些参数可以忽略掉,并且代码也更容易阅读。

3 原型

在一个纯粹的原型模式中,我们会摒弃类,转而专注于对象。基于原型的继承相比基于类的继承在概念上更为简单:一个新对象可以继承一个旧对象的属性。可以构造一个有用对象,接着构造更多和那个对象相似的对象。

用对象字面量构建一个有用的对象:

var myMammal = {
name : 'Herb the Mammal',
get_name : function ( ) {
return this.name;
},
says : function ( ) {
return this.saying || '';
}
};

为Object增加一个create方法,用来创建新的实例

if (typeof Object.create !== 'function') {
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
}

定制一个新实例:

var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
myCat.get_name = function ( ) {
return this.says( ) + ' ' + this.name + ' ' + this.says( );
};

这是一种“差异化继承”。通过定制一个新的对象,我们指明了它与所基于的基本对象的区别。

4 函数化

函数化模式有很大的灵活性,能够更好的封装和隐藏信息。

构造一个产生对象的函数,给它起的名字以一个小写字母开头,因为它并不需要使用new前缀。该函数包括4个步骤:

  • 1.它创建一个新对象。有很多的方法去构造一个对象。它可以构造一个对象字面量,或者它可以和new 前缀连用去调用一个构造函数,或者它可以使用Object.beget方法去构造一个已经存在的对象的新实例,或者它可以调用任意一个返回一个对象的函数。
  • 2.它选择性的定义私有实例变量和方法。这些就是函数中通过var语句定义的普通变量。
  • 3.它给这个新对象扩充方法。这些方法荣有特权去访问参数,以及第二步中通过var语句定义的变量。
  • 4.它返回一个新对象。

如下是一个函数化构造器的伪代码:

var constructor = function (spec, my) {
var that, 其他私有实例变量;
my = my || {};
  把共享的变量和函数添加到my中
that = 一个新对象
  添加给that的特权方法
return that;
};

5 部件

可以从一套部件中组合出对象来。例如:构造一个能够添加简单事件处理特性到任何对象上的函数。它会给对象添加一个on方法、一个fire方法和一个私有的事件注册表对象:

var eventuality = function (that) {
var registry = {}; that.fire = function (event) { // 在一个对象上触发一个事件。该事件可以是一个包含事件名称的字符串,或者是一个拥有包含事件名称的type属性的对象。
//通过‘on’方法注册的事件处理程序中匹配事件名称的函数将被调用。 var array,
func,
handler,
i,
type = typeof event === 'string' ? event : event.type; // 如果这个事件存在一组事件处理程序,那么就遍历它们并按顺序依次执行。 if (registry.hasOwnProperty(type)) {
array = registry[type];
for (i = 0; i < array.length; i += 1) {
handler = array[i]; //每个处理程序包含一个方法和一组可选参数。
//如果该方法是一个字符串形式的名字,那么就寻找到该函数。 func = handler.method;
if (typeof func === 'string') {
func = this[func];
} // 调用一个处理程序,如果该条目包含参数,那么传递它们过去。否则,传递该事件对象。 func.apply(this,handler.parameters || [event]);
}
}
return this;
}; 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;
};
return that;
};

我们可以在任何单独对象上调用eventuality,授予它事件处理方法。我们也可以赶在that被返回前在一个构造器函数中调用它。

eventuality(that);

用这种方式,一个构造器函数可以从一套部件中组装出对象来。

参考:《JavaScript语言精粹》Douglas Crockford著    赵泽欣 鄢学鹍 译

转载请注明出处:

作者:JesseLZJ
出处:http://jesselzj.cnblogs.com

JavaScript语言精粹 笔记03 继承的更多相关文章

  1. JavaScript语言精粹笔记

    JavaScript语言精粹笔记 掌握语言的每个特性可以让你出风头,但是并不推荐,因为一部分的特性带来的麻烦可能远超本身的价值.正如书中所言,坏的材料并不能雕刻出好的作品,要成为一名更好的程序员,要取 ...

  2. JavaScript 语言精粹笔记3

    方法 毒瘤 糟粕 记录一下阅读蝴蝶书的笔记,本篇为书中最后一部分:方法.代码风格.优美的特性.毒瘤.糟粕等. 方法 这一章主要介绍了一些方法集.这里写几个我不太熟悉的方法和要点吧. array.joi ...

  3. JavaScript语言精粹 笔记04 数组

    数组1 数组字面量2 长度3 删除4 列举5 混淆的地方6 方法7 维度 数组1 数组字面量 var empty = []; var numbers = [ 'zero', 'one', 'two', ...

  4. JavaScript语言精粹 笔记02 函数

    函数函数对象函数字面量调用参数返回异常给类型增加方法递归作用域闭包回调模块级联套用记忆   函数 1 函数对象 在JS中函数就是对象.对象是“名/值”对的集合并拥有一个连接到原型对象的隐藏连接.对象字 ...

  5. JavaScript语言精粹 笔记01 语法 对象

    内容比较简单,只是从头梳理一下JS的知识 语法空白标识符数字字符串语句 对象对象字面量检索更新引用原型反射枚举删除减少全局变量污染  语法 1 空白 空白可能表现为格式化字符或注释的形式.空白通常没有 ...

  6. JavaScript语言精粹 笔记06 方法

    JS包含了少量可用在标准类型上的标准方法. ArrayFunctionNumberObjectRegExpString Array array.concat(item...) concat方法返回一个 ...

  7. JavaScript语言精粹 笔记05 正则表达式

    正则表达式 正则表达式以方法的形式被用于对字符串中的信息进行查找.替换画图提取操作.可处理正则表达式的方法有:regexp.exec, regexp.test,string.match, string ...

  8. 1.javascript语言精粹笔记

    一.注释 /**/ // 采用这个 二.标识符 标识符被用于语句.变量.参数.属性名.运算符和标记三.数字 javascript只有一个单一的数字模型.它在内部被表示64位的浮点数. 没有分离出整形, ...

  9. javascript语言精粹-笔记

    walkDOM function walkTheDOM(node, func) { func(node); node = node.firstChild; while (node) { walkThe ...

随机推荐

  1. 【POJ】2329 Nearest number - 2(搜索)

    题目 传送门:QWQ 分析 在dp分类里做的,然而并不会$ O(n^3) $ 的$ dp $,怒写一发搜索. 看起来是$ O(n^4) $,但仔细分析了一下好像还挺靠谱的? poj挂了,没在poj交, ...

  2. NodeJS写模块和引入模块的例子

    nodejs自学.js function hello(){ console.log("hello world");} function s(){ console.log(" ...

  3. C# 一维码生成

    概念 一维条码即指条码条和空的排列规则,常用的一维码的码制包括:EAN码.39码.交叉25码.UPC码.128码.93码,ISBN码,及Codabar(库德巴码)等. 条形码起源于 20 世纪 40 ...

  4. [iOS]UIScrollView嵌套内容在左右拨动的时候自动被顶上问题

    遇到的问题是这样的: 适配6+没问题,但是5s就出问题.我UIScrollView嵌套了左侧UIScrollView,右侧UITableView,左右拨动切换,结果5s下拨动之后两边的View都会自动 ...

  5. 从零玩转JavaWeb系列7web服务器-----用户登录界面二维码的制作

    1.用eclipse工具新建一个Dynamic Web Project工程如下: 2.在Java Resources的src目录下新建一个包,包名称为com.it666.code 3.在com.it6 ...

  6. javaScript字符串操作

    JS自带函数concat将两个或多个字符的文本组合起来,返回一个新的字符串.var a = "hello";var b = ",world";var c = a ...

  7. Spring DI的配置使用

    1.1.1 依赖和依赖注入Spring IOC容器的依赖有两层含义:Bean依赖容器和容器注入Bean的依赖资源:a.Bean依赖容器:也就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean ...

  8. Lucene介绍及简单入门案例(集成ik分词器)

    介绍 Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和 ...

  9. 利用UUID 随机生成8位短号

    //获得8位短号 public static String[] chars = new String[] { "a", "b", "c", ...

  10. 启动图。引导页以及EAIntroView的使用

    ios启动图: 1242 x 2208 (6plus)    R5.5位置 750 x 1334   (6)           R4.7位置 640 x 960     (4/4s)      2x ...