javascript函数可以用任意多个参数来调用,而不用管函数定义时指定了几个参数。因为函数是弱类型的,没有方法去声明它所期望的参数类型,并且给任何函数传递任何类型的值都是合法的。
可选参数
当调用一个函数时,传递的参数少于声明时的参数。那么额外的参数都将以undefined值来处理。写一些在调用时可以被忽略或者可选的函数也是有用的。要达到这个目的,你必须给那些可能被忽略的参数分配一个合理的值(或指定为null),如:
// 将对象o的所有属性名添加到数组a中,并返回数组a。如果o被忽略,那么先创建,再返回
function copyPropertyNamesToArray(o,a)// 其中,a可以省略
{
if(!a) a=[];// 如果未定义或者为空,就用一个空数组
for(var property in o) a.push(property);
return a;
}
函数定义成这样,就可以非常灵活地调用:
var a=copyPropertyNamesToArray(o);// 将o的所有属性名添加到数组a中
copyPropertyNamesToArray(p,a);// 追加P的属性到数组a中
可以用双竖线操作符||这种符合语言习惯的方式来替换上面函数的第一行代码:
a = a || [];
注意:如果||的第一个参数的值为true或者可以转化为true,此操作将返回第一个参数,否则将返回第二个参数,在这里,如果定义了a并且a不为null,甚至a为empty,都会返回a。否则它将返回一个空数组。
注意在设计函数时,应该确保可选参数排在参数列表的最后。程序员不可能忽略第一个参数而传入第二个。
可变长度的参数列表:参数对象
在函数体内,arguments标识符有着特殊的意义。arguments是一个指向Arguments对象的特殊属性。Arguments对象是一个数组式的对象。他使得传递给函数的参数可以通过数字而不是通过名字来检索。他也定义了callee属性。
尽管在定义函数时指定了固定的参数个数,但是在调用时可以传入任意个参数。Arguments对象可以完全访问到这些参数,甚至是一些或者所有的未命名的。假如你定义了一个只有一个参数x的函数f。而调用时你传入了两个参数。第一个参数可以很容易地通过x或者arguments[0]获得。而第二个参数只能通过argumentts[1]来获取。还有,就像真正的数组一样,arguments有一个length属性指定了它包含的元素个数,因此,在函数f内部,arguments.length的值就是2。
arguments对象在很多时候都是很有用的。下面的例子将向你展示怎样用它来证实用正确数量的参数来调用函数:
function f(x,y,z)
{
// 检查是否传入了正确的参数个数
if(arguments.length !=3)
{throw new Error("function f called with "+arguments.length+"arguments, but it expects 3 arguments.");}
…
}
arguments对象对于javascript函数来说就有这样一种可能性:这些函数可以被写成接收任意个参数并返回其中的最大值。(和内置函数Math.max()一样,有着同样的工作方式
function()
{
var m=Number.NEGATIVE_INFINITY;
// 循环所有参数,并记录最大的。
for(var i=0;i<arguments.length;i++)
{
if(arguments[i]>m) m=arguments[i];
}
return m;
}
var largest=max(1,2,3,4,54);
注意,像这样的函数不允许无参调用。用arguments[]对象来写一些固定参数后再跟一些可有可无的参数这是完全可行的。
记住,arguments并不是一个真正的数组,它是一个arguments对象。每一个arguments对象定义了有限的元素个数和一个length属性。在技术上来说,它并不是一个数组。可以将它理解为一个有限属性的对象
arguments对象有一个特点。当一个函数有一个已命名的参数时,arguments对象的数组元素是函数参数名的同义词。arguments[]与参数名是调用同一个变量的两种不同方式。用参数名改变参数的值同样会改变arguments[]数组元素的值。反过来也是一样。如:
function(x)
{
print(x); // 显示传入的初始值。
arguments[0]=null;
print(x);// 现在显示null
}
这就证明了arguments并不是一个普通的数组。否则的话,arguments[]和x被初始化具有相同的值,但是一个改变并不会影响到另一个。
callee属性
除了数组元素之外,arguments对象还定义了callee属性用来指向被执行的函数。这个属性很少用到。但它可以允许未命名的函数递归调用自己。如:
function(x)
{
if(x<=1) return 1;
return x*arguments.callee(x-1);
}
将对象的属性当作参数
当一个函数需要三个以上的参数时,对调用者来说很难记住参数的正确顺序。为了将程序员从这种每调用一次函数就查一次函数说明书的困境中解救出来,用不计顺序的键值对的形式来传递参数将是一种好的方法。为了使这种想法生效,需要将函数定义成接收一个单独的对象作为参数,然后用户传入一个定义了键值对的object literal。如:
// 从from数组的from_start位置开始复制length个元素到to数组中的to_start位置,这些参数当然很难记
function arraycopy(/*array*/ from,/*index*/ from_start,/*array*/to,/*index*/ to_start,/*integer*/ length){…}
再看看经过改进后的函数
function easycopy(args)
{
arraycopy(args.from,
args.from_start||0,// 注意 这样就支持默认值0
args.to,
args.to_start||0,
args.length);
}
我们这样调用easycopy:
var a=[1,2,3,4];
var b=new Array(4);
easycopy({from:a,to:b,length:4});
参数类型
因为javascript是弱类型的语言,方法的参数不能声明类型也没有对所传值的类型检查。你可以在编写代码时写一些具有描述性名字也可以通过注释来标明参数的类型,就像在arraycopy函数中的一样,对于可选的参数,你可以在注释中添加"optional"这样的单词,当一个方法接受很多个参数时,你可以这样:
function max(/* number…*/){}
javascript中的类型转换是非常自由的。如果你写了一个函数接收一个字符串参数而用其它的类型去调用,你传入的值将会被转换成字符串,所有的原始类型都可以被转换成字符串,所有的对象都有toString()方法,所以这样的错误永远不会发生。
然而并不总是这样,看一下arraycopy函数,它的第一个参数是数组。如果传入的不是数组,那么执行将会失败。这样就需要我们添加代码来检查这样的错误。如果传入了错误的参数,则抛出一个异常来说明一下。这样要比执行失败时再去尝度要好得多。:
// 返回数组(或者类似数组)中所有元素的和
// 元素中的所有元素必须是数字,null 和 undefined将被忽略
function sum(a)
{
if( (a instanceof Array)||(a && typeof a == "object" && "length" in a))// 如果是数组 或者 类似数组的object
{
var total=0;
for(var i=0;i<a.length;i++)
{
var element=a[i];
if(!element) continue;// 忽略null 和 undefined
if(typeof element == "number") total+=element;
else throw new Error("sum(): all array elements must be numbers");
}
return total;
}
else throw new Error ("sum(): argument must be an array");
}
以上的sum就非常严格地检验了传入的参数,同时又可以接收类似数组并且忽略null和undefined元素。
javascript是一种语法非常宽松的弱类型语言,可以写一些对参数的类型和个数都非常宽松的函数。
function flexisum(a)
{
var total=0;
for(var i=0;i<arguments.length;i++)
{
var element=arguments[i];
if(!element) continue; // 忽略null 和 undefined
var n;
switch (typeof element)
{
case "number":
n=element;
break;
case "object":
if(element instanceof Array) n=flexisum.apply(this,element);
else n=element.valueOf();
break;
case "function":
n=element();
break;
case "string":
n=parseFloat(element);
break;
case "boolean":
n=NaN;
break;
}
if(typeof n=="number" && !isNaN(n) total+=n;
else throw new Error("sum(): can't convert "+element+" to number");
}
return total;
}
分享到:
相关推荐
2. **函数参数与返回值**:函数可以接受参数,这些参数在函数内部被用来执行特定任务。同时,函数也可以返回一个值,作为执行结果传递给调用者。这对于数据处理和计算来说至关重要。 3. **匿名函数与立即执行函数**...
1. **函数参数**: - JavaScript函数支持可选参数,可以在调用时传递任意数量的参数。 - 使用`arguments`对象可以访问所有传递给函数的参数。 ```javascript function sum() { var total = 0; for (var i = 0; ...
JavaScript函数式编程是一种编程范式,它强调将计算视为数据处理的过程,并且重视函数作为第一类公民,即函数可以作为变量赋值、作为参数传递、作为返回值返回。这种编程风格在JavaScript中尤其常见,因为它提供了...
3. **数组和集合**:学习JavaScript中的数组操作,如map、filter、reduce等高阶函数的运用,以及Set和Map等ES6新增集合类型的使用。 4. **函数**:理解闭包、作用域和this的关键概念,学习箭头函数的语法和特性。 5....
根据给定文件的信息,我们可以总结出关于JavaScript中的几个重要系统函数的知识点,这些知识点主要集中在URI编码解码、数字解析以及数值判断上。 ### 1. URI 编码与解码 #### 1.1 `encodeURI()` - **功能**:`...
在JavaScript中,函数是一等公民,这意味着函数可以被赋值给变量、作为参数传递给其他函数以及作为其他函数的返回值。函数式编程强调纯函数(pure functions)和不可变性(immutability),纯函数指的是相同的输入...
JavaScript是Web开发中不可或缺的一部分,它是一种轻量级的脚本语言,主要应用于客户端的网页交互。这篇自我总结涵盖了JavaScript函数的16到30个常用...学习并熟练掌握这些函数将极大地提升开发者在Web开发中的能力。
函数表达式、函数声明、箭头函数和默认参数都是JavaScript中函数的常见形式。 4. **对象与原型链**:JavaScript对象是键值对的集合,可以通过花括号{}创建。原型链是JavaScript继承的基础,通过__proto__属性或...
5. **默认参数**:函数参数可以设置默认值,避免因未传递参数而导致的错误。例如,`function greet(name = 'World') { console.log(`Hello, ${name}!`); }`,如果未传入`name`,则使用默认值`World`。 6. **剩余...
3. 函数:函数是JavaScript的核心特性,学习如何定义、调用函数,以及理解参数、返回值、函数表达式和函数作为值的特性。可能的练习包括函数的柯里化、高阶函数和箭头函数的使用。 4. 对象:JavaScript的对象是键值...
1. **函数**: 在JavaScript中,函数是可重复使用的代码块,可以接收参数并返回值。它们是第一类对象,这意味着函数可以作为变量赋值、作为参数传递给其他函数,甚至作为其他函数的返回值。例如,创建一个简单的函数...
`setInterval`函数可以做到这一点,它接受一个函数和一个时间间隔作为参数,每隔指定的时间就执行一次该函数。 在实际应用中,我们还需要考虑一些额外的因素,比如滚动速度的控制、是否支持暂停和继续滚动、以及在...
2. 函数式编程:JavaScript支持函数作为一等公民,可以将函数作为参数传递,也可以作为返回值。 3. 基于原型的对象:所有对象都继承自一个基础对象,通过原型链实现继承。 4. 弱引用:JavaScript具有弱引用机制,...
JavaScript 函数式编程是一种编程范式,它将函数视为第一类公民,允许它们作为其他函数的参数、返回结果,甚至可以存储在变量中。在JavaScript中,函数式编程提供了更高级别的抽象,使得代码更简洁、可读性更强,...
你将学习如何定义、调用函数,传递参数,以及理解作用域和闭包等高级概念。 JavaScript的事件驱动特性在网页开发中至关重要。通过学习DOM(文档对象模型),你可以理解如何操作网页元素,响应用户交互,如点击按钮...
JavaScript中的函数式编程是一种强大的编程范式,它源自数学中的函数理论,强调将计算视为函数的求值,而不是状态的变化或指令的...学习和实践函数式编程,对于提升JavaScript开发者的技能和解决问题的能力至关重要。
理解ECMAScript对于深入学习JavaScript至关重要,因为它规定了变量声明、函数定义、数据类型以及各种操作的规则。例如,JavaScript中的数据类型包括基本类型(如String、Number、Boolean、Null、Undefined)和引用...
本章将详细解释函数的定义、调用以及参数和返回值的使用。 第4章:数组和对象 数组用于存储多个值,而对象则用来组织和管理数据。这里会介绍数组的创建、遍历和操作,以及对象的声明、属性和方法。 第5章:事件...
JavaScript 学习 - 提高篇 在本节课程中,我们将深入探讨 JavaScript 中的...本节课程涵盖了 JavaScript 中的对象、函数、constructor 函数等高级概念,旨在帮助学习者更好地理解 JavaScript 的基本原理和高级特性。