堆栈原型图
栈:(简单数据类型)及(复杂数据类型地址)的存储仓库,代码从这里开始获取数据
堆:复杂数据的存储仓库,将数据存在此处,数据存储的地址交给栈保存,用于索引到相应的数据
案例:
在案例中,定义了四个全局变量:
var c
var num = 10
var obj1 = {item:"unchanged"}
var obj2 = {item:"unchanged"}
定义了如下函数:
var changStuff = function(a,b,c){
a = a*10
b.item ='changed'
c = {item:"changed"}
}
函数调用的方式为:
changStuff(a,obj1,obj2)
在分析之前,我们需要知道如下几点:
1.简单数据类型给函数传入参数,是传入的变量值,而非变量本身
2.复杂数据类型给函数传入参数,是传入的存在栈中的空间地址,而非空间本身
3.复杂数据类型使用数据的方式是通过:地址.属性名 来实现的,如:
var val = obj2.item 就是获取属性值,obj2.item = 'za’是改变属性值。
解析:
- 关于console.log(a)的分析
函数调用时,将变量a的值进行传入,根据a的位置可以知道,它对应于第一个形参a。语句 a =a *10 ,解析出来是:形参a的值 = 传入参数10 *10. 所以如果将形参a打印出来,发现形参a的值是100 ,而变量a的值还是10 (原因是变量a传入的是参数,而不是变量本身,传出去的只是一个拓印出去的值罢了)
var a = 10
function cc(){
a=10*10
}
cc(a)
console.log(a);
- 关于console.log(obj1.item)的分析
函数调用时,将对象obj1的值进行传入,根据obj1的位置可以知道,它对应于第二个形参b。语句:b.item =‘changed’ ,通过复杂数据类型使用数据的方式可以知道,该语句将对象obj1的属性item的属性值修改为了’changed‘
var obj1 = {item:'unchanged'}
function cc(b){
b.item = 'changed'
console.log(b);
}
cc(obj1)
console.log(obj1);
- 关于console.log(obj2)的分析
函数调用时,将对象obj2的值进行传入,根据obj2的位置可以知道,它对应于第三个形参c。语句:c = {item:‘changed’} ,通过函数传参的规则我们可以知道,此处传入的是obj2对象的地址,但是此处是一个对象赋值操作,即改变了地址内容。此时我们举一个例子:我手上有一张纸,上面写的是对象obj2存放数据的地址,此时函数需要调用obj2中的数据,我用另一张新纸,将我手中纸上的地址抄了上去,并将新纸给了函数,函数可以通过这张新纸上的地址去访问obj2上的数据,但是函数却将地址修改了,指向了另一个新的空间,此时函数手上新纸中的地址内容改变的,但是这和我手上的纸写的内容有什么关系呢?可以说是毫无关系。所以形参c的打印信息是修改的地址索引到的对象,而变量obj2的地址已经没变
var obj2 = {item:'unchanged'}
function cc(c){
c = 'changed'
console.log(c);
}
cc(obj2)
console.log(obj2);
总结
函数通过传入参数的形式调用外部定义的变量时,只有复杂数据类型的数据有可能会被通过 对象.属性名 或 数组名[索引号]的方式被修改,其它操作堆变量本身不会有影响,那些变化只会存在于形参中,函数执行完毕即被销毁