JS对象类型函数篇函数参数

JS中函数定义时不需要指定参数的类型,函数调用时也不会对传入的参数进行类型检查,甚至参数的个数也不做检查,了解这些特殊情况,避免开发出错。

参数个数

当实参比形参的个数少时,多余的形参会被设置成undefined。

function fn(a,b,c){
  console.log(c) // undefined
}

fn(1,2) 

当实参比形参的个数多时,多余的实参在函数中无法直接获取到,可以通过arguments对象获取。

function fn(a,b) {
  console.log(arguments[0],arguments[1],arguments[2]) // 1 2 3
}

fn(1,2,3)

JS函数中的参数在内部是用一个数组表示的,可以通过arguments对象访问这个参数数组,从而获取到传入给函数的每一个参数。

注意: arguments对象是一个类数组对象,不是Array对象的实例。可以使用方括号语法访问每一个元素。

arguments对象的length属性显示实参的个数,函数的length属性显示形参的个数。

function fn(a,b) {
  console.log(arguments.length) // 3
  console.log(fn.length) // 2
}
fn(1,2,3)

参数同步

在严格模式下,arguments对象的值和形参是独立的。在非严格模式下,它们的值是同步的。

// 示例1

function fn(a) {
  'use strict'
  console.log(a, arguments[0]) // 1 1
  
  a = 2
  console.log(a, arguments[0]) // 2 1
  
  arguments[0] = 3
  console.log(a, arguments[0]) // 2 3
}
fn(1)


// 示例2
function fn(a) {
  console.log(a, arguments[0]) // 1 1
  
  a = 2
  console.log(a, arguments[0]) // 2 2
  
  arguments[0] = 3
  console.log(a, arguments[0]) // 3 3
}
fn(1)

callee属性

arguments对象的callee属性是一个指针,指向拥有这个arguments对象的函数。

注意: 严格模式下禁止使用该属性,会报错

// 阶层函数
function factorial(num) {
  if(num <=1) {
	return 1
  } else {
	return num * factorial(num - 1)
  }
}

factorial(3) // 6

上面的函数有一个问题,就是函数的执行和函数名耦合在了一起,这时可以使用callee属性解决这个问题。

function factorial(num) {
  if(num <=1) {
	return 1
  } else {
	return num * arguments.callee(num - 1)
  }
}

factorial(3) // 6

由于callee属性在严格模式下报错,可以使用具名函数表达式。

var factorial = function fn(num){
  if(num <=1){
    return 1
  }else {
     return num * fn(num - 1)
  }
}
factorial(3) // 6

caller属性

arguments对象的caller属性不是一个标准属性,不赞成用于生产环境,但浏览器都支持它。该属性保存了调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值是null。

注意: 严格模式下禁止使用该属性,会报错

// 示例1
function outer() {
  inner()
}

function inner() {
  // inner是当前函数,outer是调用当前函数的函数
  console.log(inner.caller) // outer() { inner() }
}
outer()

// 示例2
function inner() {
  console.log(inner.caller)
}

inner() // null 

函数重载

函数重载简单理解就是同一个函数,可以根据不同的参数(比如类型不同或数量不同)执行不同的处理逻辑。

由于JS无法为同一个函数编写不同的定义标签,所以真正的重载是做不到的,只能通过检查传入函数中参数的类型和数量作出不同的反应,来模仿方法的重载。

function doAdd(){
    if(arguments.length == 1){
        alert(arguments[0] + 10);
    }else if(arguments.length == 2){
        alert(arguments[0] + arguments[1]);
    }
}
doAdd(10);//20
doAdd(30,20);//50

参数传递

【基本类型值】向参数传递基本类型值时,被传递的值会复制给一个局部变量(命名参数或arguments对象中的一个元素)

function fn(num) {
  num += 10
  return num
}

var count = 10
var result = fn(count)

console.log(count) // 10 原始值不会改变
console.log(result) // 20

【引用类型值】向参数传递引用类型值时,被传递的值的引用地址复制给一个局部变量,所以局部变量的变化会反映到外部函数上。

function fn(obj) {
  obj.name = 'hello'
}
var person = new Object()
fn(person)

console.log(person.name) // 'hello'

如果在函数内部重写引用类型的形参,被传递的值就会成为一个局部变量,局部变量会在函数执行结束后立即销毁

function fn(obj) {
  obj = new Object();
  obj.name = 'hello';
}
var person = new Object()
fn(person)

console.log(person.name) // undefined
优秀文章首发于聚享小站,欢迎关注!
原文地址:https://www.cnblogs.com/yesyes/p/15351892.html