变量分为值类型和引用类型,一般的数字,字符串,布尔都是值类型,而数组,对象,函数则是引用类型。
值类型 : 值类型是存储在栈中的,在我理解中,var a = 10; a = 20;这个过程中,并不是删除了10这个数据然后再次赋值给a一个20的数据,而是用20这个数据覆盖了10这个数据,就好比栈型存储结构一样,后进先出,在取值时只会取得栈顶的值所以就会取得20。
在对值类型的变脸进行复制时,var a = 10; var b = a;这个过程是对a进行一个拷贝将a中的内容拷贝一份赋值给b。在你不知道的JavaScript一书中,var b = a ;对a是一个右查询,查询的是a中的内容,将a中的内容拷贝一份赋值给b。所以a与b的修改互不影响
引用类型 : 引用类型是存储在堆中的 ,由于栈的结构比较固定无法扩展,所以对象数组这种可以扩展的数据类型就不适合存储在栈中,而堆这种存储结构内存大小不限,所以数组对象等数据类型就要存储在栈中,但是在操作时无法直接操作堆内存中的数据,只能同过
栈中的变量去存放堆中数据的地址,根据这个地址去找寻堆内存中的数据。所以 var a = {age:10}; var b = a; b.age = 20;这个时候a中的age也是20,因为var b = a 的过程中将a中存放的地址信息给了b,所以b就会根据地址的信息找到堆内存中的数据,因为
b与a指向同一块内存空间,对b与a的修改就会互相影响,因为修改的是同一块内存空间里面的数据。
但是在函数传递参数过程中,无论传递的是基本类型还是引用类型的变量,在操作函数的参数 都是值传递,而不是引用传递!!! 给一个函数传递一个引用类型的参数,并不是将引用类型的变量传递进来而是拷贝了一个副本将副本传递进来。var b = {age : 20};function fn(b) {
/*左查询右查询需要考虑清楚*/ b = {}; return b; } var a = fn(b); console.log(b);//{age : 20}; console.log(a);//{}; 这一段代码中如果是将b本身传递进来,那么b变量应该会指向一个新的内存空间也就是一个空的对象。但是结果却不是,b并没有任何的修改。这就说明在函数传参过程中,无论是基本类型还是引用类型都是依靠值传递工作的。 所以说在给函数传递引用类型的参数时,就好比一个变量赋值,把你要传递的数据做一个拷贝交给函数的参数,如果是引用类型那么就将变量中存放的堆内存的地址交给参数,所以参数和传递进来的数据指向了同一块内存空间,对参数的修改也就修改了外界的数据。但是一旦将参数进行重新赋值也就是让它指向 一个新的地址那么,那么就将切断参数与传递进来的数据,这样对参数的操作就和传递进来的数据没有任何关系了,所以传参这个过程就是值传递。 在js中经常需要对传递进来的数据进行一个初始化判断,这个过程就是如果a不是个对象,就赋值为一个空对象,对外界的a没有影响的,外界的a如果是个数字那么他还是个数字,不会有所改变的。 function fn(a){ a = ! a instance of Object || {}; }