函数
函数实际上是一个对象 函数名就是对象的key值 (一个函数对象)
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数组 里面保存了两个参数
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
所以所有的参数都是复制了一个值并传入 只是普通数据类型复制了值 复杂类型复制了其引用(引用也是一个值)