JS函数和函数参数细节详解

302 阅读2分钟

函数

函数实际上是一个对象 函数名就是对象的key值 (一个函数对象)

image.png

function test(arg1,arg2){ ... }

test: f test() // 函数键值对

test: {
	 length:2,
         name:'test',
	 arguments:{1:arg1,2:arg2}, // 参数对象
	 caller:[...],  // 函数调用者
         this:undefined,// 函数的this指向(隐藏)
	 [[Prototype]]:f(), // 函数的构造函数,
         [[Scopes]]:  // 函数的作用域链  其中保存了闭包变量  (也就是函数外能访问的内部变量)
}

参数

参数的实质 是复制了一份变量的值/或引用地址 填入argument对象(数组)中

function test(arg1,arg2){...}
const num = 1
const obj = {a:2}

test(num,obj)
// 生成的arguments对象(数组)
arguments:{1:1,2:'obj的引用'}

// 函数的参数可以理解为对arguments数组的解构 (实际上不能这么写 因为arguments对象只在函数内部生效)
function test([...arguments]){} 

arguments对象

一般来讲arguments是保存了函数参数的数组 我们这里将arguments作为对象来理解(JS中数组就是对象)

arguments:[arg1,arg2]  // 数组形式
arguments:{1:arg1,2:arg2,...} // 对象形式
// 访问arr[1] 相当于访问arr.1 

一个arguments数组 里面保存了两个参数 image.png

1 给函数传递基本类型参数时 相当于将变量复制了一份 填入arguments对象中

const num1 =10
function addNum(num){
      return num+=10
}
//将num1传入函数并修改,不会改变原来的num1。因为复制了一份num1并插入arguments对象
console.log(num1) //10
console.log(addNum(num1)) //20 

2 如果传入引用类型 (会复制引用的地址并传入)。函数内的操作会影响到原对象

const obj1 = new Object()
function setName(obj){
	obj.name = '张三'
}
函数内对传入的参数obj的操作 会影响到原对象obj1 
console.log(obj1.name//'张三'

3. 如果直接修改参数引用 相当于修改了arguments对象(数组)中的属性

function test(arg1){ // 相当于 生成arguments:{1:'obj的引用'}
	arg1.num = 2  // 可以访问到obj并修改
  arg1 = {num:2} // 这里等价于 arguments[1] = {num:1} 无法影响到外部的obj
}

const obj = {num:1}
test(obj) // 传入obj

image.png

所以所有的参数都是复制了一个值并传入 只是普通数据类型复制了值 复杂类型复制了其引用(引用也是一个值)