《JavaScript应用程序设计》一一2.12 范型编程与集合多态

2.12 范型编程与集合多态

范型编程是指在多种数据类型上提供可复用的一套算法与数据结构,这种语言机制的产生缘由在于算法通常能适配多种数据类型。范型编程一般从几种特定的数据类型实现开始入手,随后逐步将之抽象成为能够兼容更多数据类型的通用版本。
范型编程并没有对不同类型的数据做算法差异性处理,相反,被传入的每种数据类型必须实现算法中所约定的功能,这些功能被称为“接口需求”。
范型编程具有参数多态性,它是作用于范类型参数上的逻辑分支,相比之下,重载则需要对所有不同类型的参数分别创建一套处理逻辑。
范型编程的理念与函数式编程紧密相关,因为函数式编程的最佳使用场景常见于单一函数对应多种数据类型。
在多数语言中,范型编程关注的是如何让算法去兼容不同类型的集合,在JavaScript中,集合可以包含任意类型的数据结构,许多程序员为了让算法适配集合中的元素,采用了鸭子类型的代码设计方式,他们忘记了多数JavaScript的内建对象方法本身就是支持范型调用的,这些方法可以在多种数据类型上使用。
JavaScript中的集合有对象与数组两种类型,它俩的关键不同之处在于,对象采用的是键值对的组织方式,而数组中的内容则是按照次序依次排开,对象不能保证内容的顺序而数组可以,除此之外,它们的行为都极为相似。实现一个兼容所有传入集合类型的函数带来的复用价值是显而易见的。
大部分作用于数组上的函数同样也应当可以在对象上调用,举例来说,假设你想从一个数组或对象集合中获取随机值。
最为简单的方法是通过数字索引下标找到相应的随机元素,但当集合类型为对象时,需要使用重载的方式将对象转换为数组。

var toArray = function toArray(obj) {
  var arr = [],
    prop;

  for (prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      arr.push(prop);
    }
  }
  return arr;
};

randomItem()函数的实现很简单,首先确认传入集合的类型是否为数组,如果不是则将之转换为数组,最后使用内置方法Math.random()获取数组中的随机元素并返回:

var randomItem = function randomItem(collection) {
  var arr = ({}.toString.call(collection) !==
    '[object Array]')
      ? toArray(collection)
      : collection;
  return arr[Math.floor(arr.length * Math.random())];
};

test('randomItem()', function () {
  var obj = {
      a: 'a',
      b: 'b',
      c: 'c'
    },
    arr = ['a', 'b', 'c'];

  ok(obj.hasOwnProperty(randomItem(obj)),
    'randomItem works on Objects.');

  ok(obj.hasOwnProperty(randomItem(arr)),
    'randomItem works on Arrays.');
});

测试用例验证被返回的元素是否存在于目标集合中。
不同于真正意义上的范型,上述代码将对象视为一种特殊的数据类型,并在内部采用了不同的逻辑实现。由于在JavaScript中数组是对象的子集,所以从理论上看,任何作用在对象之上的操作同样适用于数组,换句话说,在JavaScript中,对象中的大部分范型方法无需做额外的逻辑处理,就可以在数组上执行。
集合的多态性对于提升代码复用性与API一致性来说是一项非常有效的策略,在诸如jQuery、Underscore这样的类库中,大部分方法同时可以兼容对象与数组。
JavaScript 1.6版本中为数组与字符串引入了不少内置的范型方法,在支持1.6版本语法的JavaScript引擎中,你可以在字符串对象上使用诸如every()这样的数组方法。

var validString = 'abc',
  invalidString = 'abcd',

  validArray = ['a', 'b', 'c'],
  invalidArray = ['a', 'b', 'c', 'd'],

  isValid = function isValid(char) {
    return validString.indexOf(char) >= 0;
  };

test('Array String generics', function () {
  ok(![].every.call(invalidString, isValid),
    'invalidString is rejected.');

  ok([].every.call(validString, isValid),
    'validString passes.');

  ok(![].every.call(invalidArray, isValid),
    'invalidArray is rejected.');

  ok([].every.call(validArray, isValid),
    'validArray passes.');
});
同理,字符串对象的方法也可以作用于数字对象。
var num = 303;

test('String number generics', function () {
  var i = ''.indexOf.call(num, 0);

  ok(i === 1,
    'String methods work on numbers.');
});

时间: 2024-08-01 21:06:35

《JavaScript应用程序设计》一一2.12 范型编程与集合多态的相关文章

C++语言基础 例程 范型编程简介

贺老师的教学链接  本课讲解 曾经的查找 //曾经的查找:顺序查找 #include <iostream> using namespace std; int main( ) { int d[10]={2,7,4,8,12,1,3,5,9,11},i,key,index=-1; cout<<"Input a key you want to search:\n"; cin>>key; for(i=0; i<10; i++) if(key == d[

《JavaScript应用程序设计》导读

前言 在本书中我们先后提到了不少Web开发类书籍,但对于那些想从头开始学习构建完整JavaScript应用的读者来说,市面上真正值得推荐的JavaScript教程又显得十分稀缺.与此同时,现在几乎每一个互联网创业公司的人员配备中都少不了资深JavaScript应用程序开发者的角色.本书旨在帮助人们了解如何构建易于扩展和维护的完整JavaScript应用. 本书并不打算向读者详细讲解JavaScript语言基础,它基于你现有的JavaScript知识结构,向你展示那些会让你的编码工作长久受益的Ja

各种程序设计的范型

过程式程序设计 确定你需要哪些过程: 采用你能找到的最好的算法. 模块程序设计 确定你需要哪些模块: 将程序分为一些模块,使数据隐藏于模块之中. 面向对象程序设计 确定你需要哪些类: 为每一个类提供完整的一组操作: 利用继承去明确地表示共性. 通用型程序设计(范型编程) 确定你需要哪些算法: 将它们参数化,使它们能够对各种各样适当的类型和数据结构工作. 摘自<C++程序设计语言(特别版)>第2章C++概览

.NET 2.0 基础类库中的范型——其他范型类

其他范型类.NET 2.0 基础类库对范型的应用当然并不仅限于范型集合和 Functional Programming.下面所列的范型类也都有其明确的设计目的和用途. Array在.NET 2.0中,Array 类扩充了对范型编程的支持.当然,Array类本身并不是范型类(出于兼容的考虑),而是提供了一系列支持范型的方法.除了前面提到的 Functional Programming 的支持外,Array 类还对以前很多基于 object 的方法提供了对应的范型版本,这样对值类型可以提高查找和排序

《JavaScript应用程序设计》一一3.3 原型

3.3 原型 原型让你能够对现有对象克隆,从而构建出一个拥有其范性方法的代理对象.工厂函数在JavaScript中,有许多灵活且简单的构造函数,所有JavaScript中的函数均可以返回对象,所以你无需再使用构造函数去构建对象.相较于构造函数,工厂函数不仅为调用者封装了对象实例化的细节,而且省略了多余的new关键字.在工厂函数中,可以组合使用JavaScript的所有语言特性,甚至能够在程序运行期间,动态修改对象的构建逻辑(而且丝毫不影响正在实例化的对象).流式API(不要与流式JavaScri

《JavaScript高级程序设计》学习笔记

系统学习JS, 从<JavaScript高级程序设计>入门,通过学习jQuery或者angularJS源码来进阶. 第1章 JavaScript简介 1.JS问世的目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作, 由Netscape主导开发,那时候微软的IE还不能独领风骚.最初叫做LiveScript,当时媒体热炒Java,于是改名为JavaScript. JavaScript和ECMAScript通常指同一门语言,但是,JavaScript是ECMA-262标准的实现和扩展

JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型_基础知识

ECMAScript是一种动态类型的语言,构建于5种简单数据类型(Undefined.Null.Boolean.Number.String)和一种复杂数据类型(Object)的基础之上.这篇文章就来复习一下简单数据类型,我会尽量从编程实践的角度来描述,下面代码运行环境为FireFox 14.0.1. 简单数据类型 简单数据类型 取值 Undefined undefined(只有一个值) Null null(只有一个值) Boolean true|false(只有两个值) Number 数值 St

《设计模式解析(第2版•修订版)》—第1章 1.6节面向对象范型

1.6 面向对象范型 设计模式解析(第2版•修订版) 使用对象将责任转移到更局部的层次 面向对象范型以对象概念为中心,一切都集中在对象上.编写代码时是围绕对象而非函数进行组织的. 对象是什么?对象传统上被定义为带有方法(面向对象领域称呼函数的术语)的数据.糟糕的是,这是一种非常有局限性的对象观.稍后我会给出一个更好的对象定义(在第8章中还会谈到).我说到对象的数据时,可能指数值和字符串这样的简单事物,也可能指其他对象. 使用对象的优点在于,可以定义自己负责自己的事物(参见表1-2).对象天生就知

《设计模式解析(第2版•修订版)》—第1章 1.2节面向对象范型之前:功能分解

1.2 面向对象范型之前:功能分解 设计模式解析(第2版•修订版) 功能分解是一种处理复杂问题的自然方法 让我们从对一种常用的软件开发方法的考察开始吧.如果给你一个任务,要编写一段代码,访问在数据库中存储的形状描述然后显示出来.按照所需要的步骤来思考,是一种很自然的选择.比如,你可能认为应该按照以下步骤解决这个问题. 1.在数据库中找到形状列表. 2.打开形状列表. 3.按某种规则将列表排序. 4.在显示器上显示各个形状. 还可以选取以上任意一个步骤,进一步分解成实现所必需的若干步.例如,可以将