JS Advance — arguments

arguments

arguments是一个用于存储函数实参的类数组(Array-Like)对象

arguments和形参一样都位于函数的AO对象中

arguments仅仅只存在于普通函数中,并不存在于箭头函数中

function foo() {
  console.log(arguments)
  /*
    {
      0: 1,
      1: 2,
      2: 3,
      3: 4,
      4: 5,
      length: 5,
      callee: foo函数的函数体
    }
  */
}

foo(1, 2, 3, 4, 5)
复制代码

使用场景

function foo() {
  // 获取长度
  console.log(arguments.length) // => 5
}

foo(1, 2, 3, 4, 5)
复制代码
function foo() {
  // 根据索引获取参数
  console.log(arguments[2]) // => 3
}

foo(1, 2, 3, 4, 5)
复制代码
let count = 0

function foo() {
  // 实现递归
  count++
  console.log(count)

  if (count < 10) {
    arguments.callee()
  }

}

foo()
复制代码

arguments 转 array

array-like意味着它不是一个数组类型,而是一个对象类型

  • 但是它却拥有数组的一些特性,比如说length,比如可以通过index索引来访问
  • 但是它却没有数组的一些方法,比如forEach、map等

所以在实际使用中,我们有可能需要将类数组对象转换为纯数组对象

手动遍历
function foo() {
  const arr = []

  for(let i = 0; i < arguments.length; i++) {
    arr.push(arguments[i])
  }

  return arr
}

console.log(foo(1, 2, 3, 4, 5))
复制代码
使用call调用数组的slice方法

模拟slice实现

Array.prototype.customSlice = function(start = 0, end) {
  end = end || this.length

  const arr = []

  // slice本身内部依旧是遍历后返回一个新的数组
  // 所以slice的调用对象即可以是纯数组对象,也可以是类数组对象
  for (let i = start; i < end; i++) {
    arr.push(this[i])
  }

  return arr
}

const arr = [1, 2, 3, 4, 5]
console.log(arr.customSlice()) // => [1, 2, 3, 4, 5]
console.log(arr.customSlice(1, 3)) // => [2, 3]
复制代码

转换

function foo() {
  return Array.prototype.slice.call(arguments)
}

console.log(foo(1, 2, 3, 4, 5))
复制代码
function foo() {
  return [].slice.call(arguments)
}

console.log(foo(1, 2, 3, 4, 5))
复制代码
ES6方法

Array.from

function foo() {
  // Array.from将数组对象和类数组对象 转换为数组对象
  return Array.from(arguments)
}

console.log(foo(1, 2, 3, 4, 5))
复制代码

展开运算符

function foo() {
  return [...arguments]
}

console.log(foo(1, 2, 3, 4, 5))
复制代码

箭头函数中没有arguments

const foo = () => console.log(arguments)

// 此时foo内部没有arguments, 所以 根据作用域链 我们会去上层作用域查找arguments
// 在这里就是全局作用域
// 1. 在浏览器中 全局作用域中是没有arguments存在的
// 2. 在node中,因为node中所有的模块都会使用IIFE包裹,编译为一个函数
//    所以在node中 全局作用域中是存在arguments对象的
foo()
复制代码
function foo() {
  return () => console.log(arguments)
}

foo(123)() // { 0: 123 }
复制代码

在ES6中,推荐使用剩余参数来取代arguments的使用,

也就是说将使用形参接收的参数未使用形参接收的参数分开了,而不是全部都存放到arguments

const sum = (num1, num2, ...nums) => console.log(nums)

sum(1, 2) // => []
sum(1, 2, 3, 4, 5) // => [3, 4, 5]
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享