1. var bb = 1;
function aa(bb) {
bb = 2;
};
aa();
console.log(bb );
2. var bb = 1;
function aa() {
bb = 2;
};
aa();
console.log(bb );
你觉得会输出什么呢,想必很多人和我一样认为会输出2 2
答案应该是1 2,为什么呢?
首先我们先来看一下作用域
1.js编程环境的顶级作用域是window对象下的范围,称为全局作用域,全局作用域中的变量称为全局变量。
注意:代码的任何位置隐士声明(不用var),都是全局变量,具有全局作用域。
2.js函数内的变量无法在函数外面访问,在函数内却可以访问函数外的变量,函数内的变量称为局部变量。
3.js函数可以嵌套,多个函数的层层嵌套构成了多个作用域的层层嵌套,这称为js的作用域链。
4.js作用域链的变量访问规则是:如果当前作用域内存在要访问的变量,则使用当前作用域的变量,否则到上一层作用域内寻找,直到全局作用域,如果找不到,则该变量为未声明。
全局变量和局部变量
全局变量:变量在全局声明,或者在代码的任何位置隐士声明(不用var),则该变量在全局可见
局部变量:变量在函数内显示申明(使用var),则在该函数内可见”
具体的全局变量和局部变量在内存中的区域
http://www.jianshu.com/p/b42715694c80
知道了作用域,我们就可以看一下这道题啦
第一个例子
在函数aa里面传了一个参数bb,bb变成了函数的局部变量,也就是相当于在函数体内声明了var bb,再去改变bb的值,bb的值在函数里面就变成了2,但是这个变化不会影响到外部作用域下的bb,因此,全局变量bb的值还是1
第二个例子
在函数内部直接给bb赋值,并没有var,此时bb是一个全局变量,给函数里面的bb赋值,相当于在函数内部重新将bb申明了一遍,并且是以全局变量的形式申明的。因此bb会输出2.
参数的传递是按值类型还是引用类型传递的
上面的例子是参数为基本类型的值,那么向参数传一个对象会怎么样呢?看下面这个例子
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name);
这端代码会输出Nicholas,看到这个结果,很多人会认为,在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的,其实不是这样的, 我们可以看一下下面这个例子。
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name);
这个会输出Nicholas,而不是Greg。
其实是这样的,如果person是按引用传递的,obj是person的引用,obj指向一个新对象,那么person就会自动被修改为指向其name属性值为"Greg"的新对象。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。下面,我们就用图示来看一下
首先 person将指向堆的地址赋给obj,此时,obj也指向了同一块地址空间。
但是当obj指向了堆中的另一块空间(new Object)的时候,obj里面存的指向堆的地址没有变化,因此他还是指向之前的空间(Object)
因此我们得出结论