`

JavaScript 的怪癖 5:参数的处理

 
阅读更多

原文:JavaScript quirk 5: parameter handling

译者:zhmengqing


此文是 javascript 的 12 个怪癖(quirks) 系列的第五篇。

JavaScript 参数处理的基本原理很简单,高级的任务都需要手动操作。 本文首先关注其基本原理然后再行扩展。

1、参数处理的基本原理

JavaScript 的参数处理包括两个要点

1.1、要点:你可以传递任意数量的参数

当调用一个 function 时,你想传递多少参数都可以,这与该函数声明了多少个正式的参数无关。 缺失参数的值是undefined,多出来的参数则直接被忽略掉。

我们用以下的函数做个示范:

function f(x, y) {
    console.log('x: '+x);
    console.log('y: '+y);
}

你可以用任意数量的参数调用这个 function

> f()
x: undefined
y: undefined

> f('a')
x: a
y: undefined

> f('a', 'b')
x: a
y: b

> f('a', 'b', 'c')
x: a
y: b

1.2要点:所有传递的参数都储存在 arguments 中

所有传递的参数都储存在一个很特别、很像 Array(继续看就能知道为什么了)的变量里,arguments。 通过下面的function 我们来看下这个变量怎么用的:

function g() {
    console.log('Length: '+arguments.length);
    console.log('Elements: '+fromArray(arguments));
}

下面是 fromArray 函数,它把 arguments 转换成 array 这样就能存入数据了,调用 g()

> g()
Length: 0
Elements:
> g('a')
Length: 1
Elements: a
> g('a', 'b')
Length: 2
Elements: a,b

无论明确声明了多少个参数,arguments 是永远在那里的,它总是包含所有实际的参数。

2、参数传递了吗?

如果调用者没有提供参数,那么 undefined 就会传递给 function。 因为 undefined 是一个虚拟值[1],你可以用一个 if 条件语句来检验它是否存在:

function hasParameter(param) {
    if (param) {
        return 'yes';
    } else {
        return 'no';
    }
}

这样,你不传参数与传入 undefined 获得的结果是一样的:

'no'
> hasParameter(undefined)
'no'

测试代码对真实值(truthy)同样有效:

> hasParameter([ 'a', 'b' ])
'yes'
> hasParameter({ name: 'Jane' })
'yes'
> hasParameter('Hello')
'yes'

而对于虚拟值(falsy)的会用是需要多加小心的。 比如 false0 以及空字符串都被解析为缺失参数:

> hasParameter(false)
'no'
> hasParameter(0)
'no'
> hasParameter('')
'no'

这段代码足以证明。 你必须要多加注意,因为代码变得更加紧凑与调用者是否忽略了一个参数还是传递了 undefined 或者null 都无关。

3、参数的默认值

以下的 function 可以传入 0 或者其他参数,x 和 y 如果未传参数则会是 0,以下是一种表现方式:

function add(x, y) {
    if (!x) x = 0;
    if (!y) y = 0;
    return x + y;
}

交互后:

> add()
0
> add(5)
5
> add(2, 7)
9

你可以用 or 运算符(||)使 add() 更简洁。 如果为真这个运算符会返回第一个值否则返回第二个。

例如:

> 'abc' || 'def'
'abc'
> '' || 'def'
'def'
> undefined || { foo: 123 }
{ foo: 123 }
> { foo: 123 } || 'def'
{ foo: 123 }

我们用 || 来指定参数默认值:

function add(x, y) {
    x = x || 0;
    y = y || 0;
    return x + y;
}

4、任意数量的参数

你也可以用 arguments 来接收任意数量的参数,其中一个例子是以下的函数 format(),它在 C 函数 sprintf 之后输出语句:

> format('Hello %s! You have %s new message(s).', 'Jane', 5)
'Hello Jane! You have 5 new message(s).'

第一个参数是一个样式,由 %s 标记空白,后面的参数则填入这些标记,简单的 format 函数实现如下:

function format(pattern) {
    for(var i=1; i < arguments.length; i++) {
        pattern = pattern.replace('%s', arguments[i]);
    }
    return pattern;
}

注意:循环跳过了第一个参数(arguments[0]) 并且忽略了 pattern

5、强制执行一定数量的参数

如果你想要强制调用者执行一定数量的参数,你就要在运行阶段检查 arguments.length

function add(x, y) {
    if (arguments.length > 2) {
        throw new Error('Need at most 2 parameters');
    }
    return x + y;
}

6、arguments 不是 array

arguments 并不是 array,它只是很像 array,你可以获取第 i 个参数比如 arguments[i], 你也可以检查它有多少个参数比如 arguments.length。 但是你不能用 Array 的方法如 forEach 或者 indexOf。 更多详情与解答会在「怪癖8(未翻译)」中进行讨论,作为一个预习,以下函数能将一个类似 array 的值转换为 array

function fromArray(arrayLikeValue) {
    return Array.prototype.slice.call(arrayLikeValue);
}

7、参考

[1] JavaScript quirk 1: implicit conversion of values [解释了“真实值(truthy)”与“虚拟值(falsy)”]

14
0
分享到:
评论

相关推荐

    javascript_fun:简单的 javascript 脚本和示例

    在这个压缩包中,我们可以期待找到一系列用于演示JavaScript核心概念、函数以及一些可能的怪癖的代码片段。 在JavaScript的世界里,学习并理解以下几个关键知识点至关重要: 1. 变量与数据类型:JavaScript是动态...

    type:运行时验证和JavaScript类型处理

    类型运行时验证和JavaScript类型处理尊重语言本性并承认其怪癖允许以受限形式强制执行(明确拒绝无效输入,规范允许的类型偏差) 没有隐含翻译,已编写为可在所有ECMAScript 3+引擎中使用用例验证在公共API端点中...

    wwalkthiswweh:一个有趣的基于React的工具,用于生成特定于字符的打字怪癖

    5. **事件处理**:JavaScript广泛用于处理用户与网页的交互,通过addEventListener()方法添加事件监听器,触发相应的事件处理函数。 6. **异步编程**:包括回调函数、Promise、async/await等,用于处理非阻塞操作,...

    从零开始学习jQuery (2).

    - **URL操作**:包含了一些处理URL的功能,如解析查询参数等。 接下来,我们将详细介绍每一类工具函数的具体用途和示例。 #### 浏览器及特性检测 在进行跨浏览器开发时,了解浏览器的具体特性和限制至关重要。...

    jsStrange

    5. **JavaScript的怪癖和陷阱**:JavaScript有一些独特的行为,比如hoisting(变量提升)、隐式类型转换、this的指向等,jsStrange可能对这些进行了深入探讨。 6. **JavaScript的新特性**:如果项目较新,可能涵盖...

Global site tag (gtag.js) - Google Analytics