欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Javascript Rest参数和拓展操作实例讲解

程序员文章站 2023-11-16 11:54:58
javascript的许多内置函数都支持任意数量的参数,比如math.max(arg1, arg2, ..., argn),object.assign(dest, src1, .....

javascript的许多内置函数都支持任意数量的参数,比如math.max(arg1, arg2, ..., argn),object.assign(dest, src1, ..., srcn)等等

rest参数“...”

一个函数可以被任意个参数调用,例如:

function sum(a, b) {
  return a + b;
}

alert( sum(1, 2, 3, 4, 5) );

使用多个参数来调用函数并不会报错,当然只有前面两个参数会被使用。在javascript里我们可以使用rest参数来定义不确认个数的参数,即使用三个点“...”,它表示将多余的参数接受并放到一个数组里,例如:

function sumall(...args) { // args is the name for the array
  let sum = 0;

  for (let arg of args) sum += arg;

  return sum;
}

alert( sumall(1) ); // 1
alert( sumall(1, 2) ); // 3
alert( sumall(1, 2, 3) ); // 6

我们也可以指定确定参数个数,例如:

function showname(firstname, lastname, ...titles) {
  alert( firstname + ' ' + lastname ); // julius caesar

  // the rest go into titles array
  // i.e. titles = ["consul", "imperator"]
  alert( titles[0] ); // consul
  alert( titles[1] ); // imperator
  alert( titles.length ); // 2
}

showname("julius", "caesar", "consul", "imperator");

需要注意的是rest参数必须放在参数列表的最后面,否则会报错误,例如:

function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
  // error
}

“arguments”参数变量

javascript的函数都有一个默认的参数变量arguments,它包含函数所有的参数变量,例如:

function showname() {
  alert( arguments.length );
  alert( arguments[0] );
  alert( arguments[1] );

  // it's iterable
  // for(let arg of arguments) alert(arg);
}

// shows: 2, julius, caesar
showname("julius", "caesar");

// shows: 1, ilya, undefined (no second argument)
showname("ilya");

在rest参数没出现的时候,javascript是使用arguments参数来获取所有的参数,由于历史原因它被保留至今。与rest参数不同的是,arguments参数是类数组和可迭代的,而不是真正的数组,故不能使用arguments.map(...)

箭头函数没有arguments

需要注意的是,箭头函数是没有arguments参数的,当我们访问箭头函数的arguments时,它默认使用外部函数的arguments,例如:

function f() {
  let showarg = () => alert(arguments[0]);
  showarg();
}

f(1); // 1
在前面我们已经知道剪头函数没有this,而且它的this是使用外部函数的this,在这里,arguments也是一样一样的~

拓展操作

前面我们已经知道如何从参数列表里获取一个数组,当有时候我们需要做的事情却是相反的,例如下面这个例子:

alert( math.max(3, 5, 1) ); // 5

let arr = [3, 5, 1];

alert( math.max(arr) ); // nan

math.max()对指定参数是正常运作的,但对于数组参数则发生错误,这是因为math.max()接受的是参数列表,而不是一个数组。

为了解决这个问题,拓展操作就被引入进来了,看下面这个例子:

let arr = [3, 5, 1];

alert( math.max(...arr) ); // 5 (spread turns array into a list of arguments)

这里的...arr就是拓展操作,只要参数是可迭代的,就可以使用拓展操作,例如array,string等等

我们也可以传递多个拓展操作参数,例如:

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

alert( math.max(...arr1, ...arr2) ); // 8

也可以跟普通参数组合,例如:

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

alert( math.max(1, ...arr1, 2, ...arr2, 25) ); // 25

对于数组合并函数也是一样,例如:

let arr = [3, 5, 1];
let arr2 = [8, 9, 15];

let merged = [0, ...arr, 2, ...arr2];

alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)

其实拓展操作的原理是将参数进行迭代并逐一返回该值,类似于for...of,这也是为什么拓展操作要求参数必须为可迭代,例如对string进行拓展操作:

let str = "hello";

alert( [...str] ); // h,e,l,l,o

..str操作后返回“h,e,l,l,o”,再将返回的内容放入数组中

在前面我们学习了array.from()这个方法,我们也可以用它来转换字符串为数组,与上面例子的结果一样,如下:

let str = "hello";

// array.from converts an iterable into an array
alert( array.from(str) ); // h,e,l,l,o

但是这里array.from()和拓展操作还是有细微的区别的:

(1)array.from()支持可迭代对象和类数组对象;

(2)拓展操作只支持可迭代对象;

对于将对象转换为数组,array.from()一般使用得更多