Effective JavaScript Item 55 接受配置对象作为函数參数
接受配置对象作为函数參数
尽管保持函数接受的參数的顺序非常重要,可是当函数可以接受的參数达到一定数量时。也会让用户非常头疼:
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;
}
总结
- 使用可选的配置对象来让API更具可读性。
- 配置參数中的属性都应该是函数的可选參数。
- 使用extend工具函数来简化使用了配置对象的代码。
Effective JavaScript Item 55 接受配置对象作为函数參数的更多相关文章
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- [c++]基类对象作为函数參数(赋值兼容规则)
编程处理教师的基本情况. 要求: 1.定义一个"person"类.用来存储及处理人的姓名.性别.年龄,成员函数自定: 2.定义"teacher"类,公有继承&q ...
- C++容器类对象函数參数问题
总之中的一个句话:容器类对象作为函数參数,与整数类型作为函数參数的传递特性同样. 验证程序 #include "stdafx.h" #include <iostream> ...
- JavaScript的最大函数參数长度和最大栈深度检測
一般代码也许不会涉及最大參数长度和最大栈深度,但某些特殊场合,检測这两个參数还是有必要的.比如:用递归计算斐波那契数列的第n个值,不了解最大栈深度,难免显得肤浅.又比如:将一串charCode转成St ...
- Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数
本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...
- Effective JavaScript Item 51 在类数组对象上重用数组方法
Array.prototype对象上的标准方法被设计为也能够在其他对象上重用 - 即使不是继承自Array的对象. 因此,在JavaScript中存折一些类数组对象(Array-like Object ...
- Effective JavaScript Item 54 将undefined视为"没有值"
将undefined视为"没有值" JavaScript中的undefined是一个特殊的值:当JavaScript没有提供详细的值时.它就会产生undefined. 比方: 未被 ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
- Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数
作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...
随机推荐
- JAVA学习笔记 -- 读写XML
XML是一种可扩展标记语言 以下是一个完整的XML文件(也是下文介绍读写XML的样本): <? xml version="1.0" encoding="UTF-8& ...
- FPS计算New
using UnityEngine; using System.Collections; public class CarGUI : MonoBehaviour { private const flo ...
- Unity3D Gamecenter 得分上传失败的处理
Unity3DGamecenter 得分上传失败的处理. 常常会有种情况是,玩家在地铁或者飞机上没法通过wifi或者3G连接到服务器,从而会导致上传分数失败 解决方法: 这时候需要把得分存在Playe ...
- hookup_2.10-0.2.3.jar包下载
hookup_2.10-0.2.3.jar包下载地址,自己也做一个记录.同一时候也给须要的朋友提供一个方便,希望对大家有所帮助.下载地址:http://www.59biye.com/jar/cont/ ...
- 记一则Linux病毒的处理
今天某项目经理反馈学校的某台服务器不停的向外发包,且CPU持续100%,远程登录后查看发现有一长度为10的随机字符串进程,kill掉,会重新生成另外长度为10的字符串进程.删除文件也会重复生成,非常痛 ...
- CV-视频分析:静态背景下的运动检测
ref : Chapter 2 Motion Detection in Static Backgrounds. [ Github :…… ] -------------------------- ...
- Call to undefined function mysql_connect()
Fatal error: Call to undefined function mysql_connect() in /data/www/qy_b2b/include/db_mysql.class.p ...
- [机器学习实战] k邻近算法
1. k邻近算法原理: 存在一个样本数据集,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对 ...
- 多校第九场Arithmetic Sequence题解
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5400 题意:给定等差数列的差值d1,d2.问长度为n的数列中有多少个满足条件的子序列,条件为子序列中 ...
- mysql init_connect
init_connect 服务器为每个连接的客户端执行的字符串.字符串由一个或多个SQL语句组成.要想指定多个语句,用分号间隔开.例如,每个客户端开始时默认启用autocommit模式.没有全局服务器 ...