接受配置对象作为函数參数

尽管保持函数接受的參数的顺序非常重要,可是当函数可以接受的參数达到一定数量时。也会让用户非常头疼:

var alert = new Alert(100, 75, 300, 200,
"Error", message,
"blue", "white", "black",
"error", true);

随着函数的不断重构和进化。它可以接受的參数或许会越来越多。终于就像上面的样例那样。

对于这样的情况。JavaScript能够使用一个配置对象来替代以上的全部參数:

var alert = new Alert({
x: 100, y: 75,
width: 300, height: 200,
title: "Error", message: message,
titleColor: "blue", bgColor: "white", textColor: "black",
icon: "error", modal: true
});

这样做尽管会让代码略微冗长一些,可是毫无疑问它的优点是非常明显的:配置对象中的每一个属性的名字就好比是一份文档,来告诉用户这个属性是干什么用的。特别是对于布尔值。单独的传入true和false是非常难推断它的真实意图的。

使用这样的方式的另外一个优点是,全部的属性都是可选的。

假设配置对象中没有出现某个属性。那么就是用默认值来取代它。

var alert = new Alert(); // use all default parameter values

假设函数须要接受必须的參数,那么不妨将它放在配置对象的外面,就像以下这样:

var alert = new Alert(app, message, {
width: 150, height: 100,
title: "Error",
titleColor: "blue", bgColor: "white", textColor: "black",
icon: "error", modal: true
});

配置对象中的全部属性都是函数可以接受的可选參数,而app和message则是必需要传入的參数。

对于配置对象的处理,能够像以下这样:

function Alert(parent, message, opts) {
opts = opts || {}; // default to an empty options object
this.width = opts.width === undefined ? 320 : opts.width;
this.height = opts.height === undefined
? 240
: opts.height;
this.x = opts.x === undefined
? (parent.width / 2) - (this.width / 2)
: opts.x;
this.y = opts.y === undefined
? (parent.height / 2) - (this.height / 2)
: opts.y;
this.title = opts.title || "Alert";
this.titleColor = opts.titleColor || "gray";
this.bgColor = opts.bgColor || "white";
this.textColor = opts.textColor || "black";
this.icon = opts.icon || "info";
this.modal = !!opts.modal;
this.message = message;
}

对于可选的配置对象,首先使用Item 54中介绍的方法当它在真值推断中返回false时,使用空对象替换它。

上述的代码还有进一步优化的空间:通过使用对象扩展或者合并的函数。

在非常多JavaScript的库和框架中都有一个extend函数,它接受一个目标对象和一个源对象,然后将源对象中的属性复制到目标对象中:

function Alert(parent, message, opts) {
opts = extend({
width: 320,
height: 240
});
opts = extend({
x: (parent.width / 2) - (opts.width / 2),
y: (parent.height / 2) - (opts.height / 2),
title: "Alert",
titleColor: "gray",
bgColor: "white",
textColor: "black",
icon: "info",
modal: false
}, opts); this.width = opts.width;
this.height = opts.height;
this.x = opts.x;
this.y = opts.y;
this.title = opts.title;
this.titleColor = opts.titleColor;
this.bgColor = opts.bgColor;
this.textColor = opts.textColor;
this.icon = opts.icon;
this.modal = opts.modal;
}

通过extend函数,不再须要时常对每一个属性进行推断。上述代码中的第一个extend函数用来在width和height属性没有被设置使设置默认值,由于在第二个extend函数中会依据它们进行计算。

假设全部的属性终于会被赋值到this对象上,那么以上代码能够简化成以下这样:

function Alert(parent, message, opts) {
opts = extend({
width: 320,
height: 240
});
opts = extend({
x: (parent.width / 2) - (opts.width / 2),
y: (parent.height / 2) - (opts.height / 2),
title: "Alert",
titleColor: "gray",
bgColor: "white",
textColor: "black",
icon: "info",
modal: false
}, opts);
extend(this, opts);
}

extend函数的实现通常都会遍历源对象的属性,然后假设该属性的值不是undefined时,会将它复制到目标对象上:

function extend(target, source) {
if (source) {
for (var key in source) {
var val = source[key];
if (typeof val !== "undefined") {
target[key] = val;
}
}
}
return target;
}

总结

  1. 使用可选的配置对象来让API更具可读性。
  2. 配置參数中的属性都应该是函数的可选參数。

  3. 使用extend工具函数来简化使用了配置对象的代码。

Effective JavaScript Item 55 接受配置对象作为函数參数的更多相关文章

  1. Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表

    本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...

  2. [c++]基类对象作为函数參数(赋值兼容规则)

    编程处理教师的基本情况. 要求: 1.定义一个"person"类.用来存储及处理人的姓名.性别.年龄,成员函数自定: 2.定义"teacher"类,公有继承&q ...

  3. C++容器类对象函数參数问题

    总之中的一个句话:容器类对象作为函数參数,与整数类型作为函数參数的传递特性同样. 验证程序 #include "stdafx.h" #include <iostream> ...

  4. JavaScript的最大函数參数长度和最大栈深度检測

    一般代码也许不会涉及最大參数长度和最大栈深度,但某些特殊场合,检測这两个參数还是有必要的.比如:用递归计算斐波那契数列的第n个值,不了解最大栈深度,难免显得肤浅.又比如:将一串charCode转成St ...

  5. Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数

    本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...

  6. Effective JavaScript Item 51 在类数组对象上重用数组方法

    Array.prototype对象上的标准方法被设计为也能够在其他对象上重用 - 即使不是继承自Array的对象. 因此,在JavaScript中存折一些类数组对象(Array-like Object ...

  7. Effective JavaScript Item 54 将undefined视为&quot;没有值&quot;

    将undefined视为"没有值" JavaScript中的undefined是一个特殊的值:当JavaScript没有提供详细的值时.它就会产生undefined. 比方: 未被 ...

  8. Effective JavaScript Item 37 认识this的隐式指向

    本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...

  9. Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数

    作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...

随机推荐

  1. winfrom 底层类 验证码

    效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzgxNjcwOQ==/font/5a6L5L2T/fontsize/400/fill/I ...

  2. 怎样推断多个字段组成的keyword在另外一张表中是否存在

    怎样推断多个字段组成的keyword在另外一张表中是否存在 老帅(20141107) 1.首先推断一个keyword在另外一张表中是否存在非常easy! SELECT * FROM a WHERE a ...

  3. <译>Flink官方文档-Flink概述

    Overview This documentation is for Apache Flink version 1.0-SNAPSHOT, which is the current developme ...

  4. oracle 查询 函数练习

    /*--以下代码是对emp表进行显示宽度设置col empno for 9999;col ename for a10;col job for a10;col mgr for 9999; col hir ...

  5. python内置函数、匿名函数、递归

    python3--内置函数 内置函数: 截止到python 3.6.2 版本,现在python一共提供了68个内置函数:即python提供给你直接可以拿来使用的所有函数.   内置函数  (点击函数查 ...

  6. Could not create and/or set value back on to object .

    严重: Error building beanorg.springframework.beans.factory.UnsatisfiedDependencyException: Error creat ...

  7. Yii Framework2.0开发教程(3)数据库mysql入门

    沿用教程(2)的代码 第一步.在本地mysql数据库中新建数据库zhyoulun 第二步.在数据库中新建表并插入若干条数据 CREATE TABLE `country` ( `code` CHAR(2 ...

  8. iloc[[i]] 和 loc[[i]] 的区别

    In [2]: df Out[2]: A B 0 1.068932 -0.794307 2 -0.470056 1.192211 4 -0.284561 0.756029 6 1.037563 -0. ...

  9. SSH整合简单例子

    说明:简单SSH整合,struts版本2.3.32,spring版本3.2.9,hibernate版本3.6.10 一.开发步骤 1 引jar包,创建用户library.使用的包和之前博文相同,可以参 ...

  10. 矩阵乘法C语言实现

    /* 矩阵乘法C语言实现 Slyar 2009.3.20 */   #include <stdio.h> #include <stdlib.h>   /* 给 int 类型定义 ...