《JavaScript应用程序设计》一一2.11 多态函数

简介:

本节书摘来华章计算机出版社《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);

相关文章
|
1天前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
10 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
14天前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
16天前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
24天前
|
JavaScript 前端开发
js教程——函数
js教程——函数
21 4
|
2月前
|
JavaScript 前端开发 安全
JavaScript函数详解
JavaScript函数的详细解析,包括函数的定义和调用方式(如一般格式、匿名函数、构造函数、自调用函数、箭头函数和严格模式)、函数参数(arguments对象、可变参数、默认参数值)、闭包的概念和应用实例。
JavaScript函数详解
|
24天前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
15 2
|
26天前
|
JavaScript 前端开发 Java
【javaScript数组,函数】的基础知识点
【javaScript数组,函数】的基础知识点
22 5
|
26天前
|
JavaScript 前端开发
Node.js 函数
10月更文挑战第5天
19 3
|
30天前
|
前端开发 JavaScript
探索JavaScript函数基础
探索JavaScript函数基础
16 3
|
1月前
|
JavaScript 前端开发
在JS中如何声明一个函数
在JS中如何声明一个函数
24 2