博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JavaScript应用程序设计》一一2.11 多态函数
阅读量:6656 次
发布时间:2019-06-25

本文共 2964 字,大约阅读时间需要 9 分钟。

本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第2章,第2.11节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.11 多态函数

在计算机学科中,多态性意味一件事物的行为取决于它当前所处的上下文环境,就像单词一样,在不同的句子中的含义也不尽相同,如下例中“东西”一词。

· 迈尔斯是韩国东西大学专门研究北韩官方宣传与传播的教授。
· 据谣传这所房间每天夜里都有什么东西吼叫。
· 这是个交通枢纽,铁路由此向东西南北伸展出去。
同理,多态函数意味着函数在执行期间的行为由传入的具体参数决定,在JavaScript中,这些参数存储在一个被称为arguments的类数组对象中,说它是类数组是因为它本身不具备Array类的实例方法。
使用Array.prototype.slice()可以对数或类数组对象进行浅拷贝操作。
你可以从Array类的原型对象上“借用”slice()方法,这种方法借用机制,我们称之为“方法代理”,调用方式如下:
var args = Array.prototype.slice.call(arguments, 0);
这将返回一个真正意义上的数据,不过这种语法看起来有一些冗余,我们换一种写法:

var args = [].slice.call(arguments, 0);

我们使用方括号语法创建了一个用来被slice()方法代理的空数组对象,这听上去感觉会对性能造成一定损耗,不过对JavaScript引擎来说创建空数组是一件极为迅速的操作,根据反复性能测试的数据结果来看,这项操作对内存与性能的影响是微乎其微的。

你可以使用这种方法创建一个对入参进行排序的函数:

function sort() {  var args = [].slice.call(arguments, 0);  return args.sort();}test('Sort', function () {  var result = sort('b', 'a', 'c');     ok(result, ['a', 'b', 'c'], 'Sort works!');});

因为arguments不是一个真正意义上的数组,所以它没有sort()方法。不过你可以通过slice()方法将arguments对象转变为一个真数组,之后再调用数组方法sort()返回一个经过排序的数组。

多态函数需要判断第一个参数的类型来决定后续的执行流程。现在args已经是数组,可以使用shift()方法获取第一个参数:
var first = args.shift();
若第一个参数类型是String,则进入分支流程:

function morph(options) {  var args = [].slice.call(arguments, 0),    animals = 'turtles'; // Set a default  if (typeof options === 'string') {    animals = options;    args.shift();  }  return('The pet store has ' + args + ' ' + animals    + '.');}test('Polymorphic branching.', function () {  var test1 = morph('cats', 3),    test2 = morph('dogs', 4),    test3 = morph(2);  equal(test1, 'The pet store has 3 cats.', '3 Cats.');  equal(test2, 'The pet store has 4 dogs.', '4 Dogs.');  equal(test3, 'The pet store has 2 turtles.',    'The pet store has 2 turtles.');});

方法调度

方法调度是指对象在接收到外界的消息时再决定其具体行为。在JavaScript中,接受消息的对象先检查自己是否有方法,如果没有,则查找原型对象,如果还没有,则查找父级原型对象,如此往复,直到找到匹配的方法随后将参数传入并调用,这在JavaScript这种基于原型的语言中被称为行为代理。
在程序运行期间根据入参的类型选择合适的函数执行,这种多态性我们称为动态调度。某些语言对动态调度有特殊语法支持,而在 JavaScript中的一般实现是,在一个方法中获取入参,随后根据入参决定另一个方法的调用。

var methods = {    init: function (args) {      return 'initializing...';    },    hello: function (args) {      return 'Hello, ' + args;    },    goodbye: function (args) {      return 'Goodbye, cruel ' + args;    }  },  greet = function greet(options) {    var args = [].slice.call(arguments, 0),      initialized = false,      action = 'init'; // init will run by default    if (typeof options === 'string' &&        typeof methods[options] === 'function') {      action = options;      args.shift();    }    return methods[action](args);  };test('Dynamic dispatch', function () {  var test1 = greet(),    test2 = greet('hello', 'world!'),    test3 = greet('goodbye', 'world!');  equal(test2, 'Hello, world!',    'Dispatched to hello method.');  equal(test3, 'Goodbye, cruel world!',    'Dispatched to goodbye method.');});

动态调度机制在jQuery的插件中较为常见,解决了开发人员为了增加插件中的方法而去污染jQuery原型链的问题。利用动态调度,你可以先在jQuery原型链中注册一个插件名称,随后就可以在此名称上任意添加你所需要的方法,插件使用者则通过下列方式调用你的方法。

$(selection).yourPlugin('methodName', params);

转载地址:http://xcato.baihongyu.com/

你可能感兴趣的文章
事件自调用 - 回复 maxcool 的问题
查看>>
Horizon View 6.0 基于RDS的应用发布
查看>>
ubuntu下系统重启dns就被清空的解决方案
查看>>
Ant Examples
查看>>
建立C语言动态链接库
查看>>
红帽企业存储管理之iscsi简单应用
查看>>
Rsync安装使用
查看>>
更改Linux系统日志的时间格式
查看>>
FC-SAN vs. IP-SAN详细技术比较
查看>>
sequioadb源码分析
查看>>
基于嵌入式Linux系统设备驱动程序的开发
查看>>
【smart-transform】取自 Atom 的 babeljs/coffeescript/typescript 智能转 es5 库
查看>>
基于S3C6410的Touch驱动详解
查看>>
使用Jekyll托管github pages的好处
查看>>
java、javaw和javaws的区别
查看>>
Git 远程分支
查看>>
华为S9300、s5700交换机端口镜像配置
查看>>
按下Enter焦点移至下一个控件的实现js代码
查看>>
zabbix系统日志文件监控key
查看>>
Salttack笔记
查看>>