Js中所有函数的参数传递都是按值传递的,也就是把函数外面的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样.而JS中某种意义上来说只包含两种类型的变量,即基本类型和引用类型。 这两种类型的变量解析方式完全不同。在Js中,定义变量进行初始化就会开辟空间。
一、基本类型传参
对于基本类型(Undefined、Null、Boolean、Number、String)会在栈空间中开辟空间,存储值本身。 赋值时将栈空间中的内容复制一份进行赋值,而不同的变量有不同的栈空间,互不影响。
function test(num) {
num = 100
num++
return num
}
let num = 10
test(num)
console.log(num) // 10
console.log(test(num)) // 101
这段代码主要是涉及到实参和形参传递时,如果类型是值类型的时候的特性,值类型数据在做为参数传递的时候,会将值的副本赋值一份进行传递,方法的形参是一个局部遍历,同时如果变量是值类型,那么是将实参的值的副本复制一份进行赋值,那么方法中的形参的操作和实参没有任何的关系了,所以num打印出的结果是10,test(num)打印出的结果才是101
二、引用类型传递参数
对于引用类型(Array、Object、Function)会在栈空间中开辟空间,存储堆空间的引用地址,真正的值存储在堆空间。 赋值时也是将栈空间中的内容复制一份进行赋值,造成形参和实参本质上指向同一个堆空间,修改其中一个,另外一个也会变化。
function test(arr) {
arr[0] = 100
arr[0]++
}
let nums = [10, 20, 30]
test(nums)
console.log(nums[0]) // 101
这段代码主要涉及到引用类型的数据做为参数传递时的特性 引用类型做为参数传递,传递的是变量的引用地址,会造成实参和形参指向同一个地址空间,修改其中一个,另外一个也会变化。所以这个题目中,方法中对arr[0]的修改,会改变外面的nums的值,所以答案为101
进一步验证引用类型传参
function test(obj) {
obj.name = "James"
obj = {}
obj.name = "Kevin"
}
let person = {}
test(person)
console.log(person.name) // James
在这段代码中,给obj添加了新的属性name之后,又将obj定义为一个新的对象并重新为name属性赋了新值。这说明即使在函数内部修改了参数的值,但原始的引用还保持不变。在函数内部定义的新的对象obj,只是函数的内部对象而已。