前端基础知识整理(一)
javascript 变量赋值问题,连续赋值问题
引用http://www.jb51.net/article/10992.htm
比如
<script> var x = "this is string"; var y = x; x="ni hao"; alert(y) </script>
你可能一下子知道alert出来的就是“this is string”,没错,但对于用Java语言的程序员来说,var y=x 应该是把x在存储器中的地址(指针)赋给y变量才对,因此他们觉得应该alert出“ni hao”才会更符合Java语言的习惯,但JavaScript语言不是这样,字符串的赋值是直接量操作,直接把数据copy给y的存储空间。
再看例子2
var x = ["hello"] // 这是一个数组,只有一个元素,并且该元素为字符串类型 var y = x; x[0] = "world"; alert(y[0]);
如果你还以为alert出来的是“hello”,那就错了。当 var y = x 时,x不是已经把它的数组给了y吗?但事实上却不是这样, 当 var y = x 时,x传的是它在存储器中的地址(指针)!x[0]=”world” 修改了在原存储位置上的数据,因此alert(y[0])就是拿x的新值出来alert。混乱了吧?怎么一会儿是直接量一会儿是引用量呢?
再看例子3
var x = ["hello"] // 这是一个数组,只有一个元素,并且该元素为字符串类型 var y = x; x = ["ni","hao"]; // x 将变成一个新的数组了。 alert(y[0]);
你的眼睛告诉你,alert出来的是“hello”!
执行 var x = [“hello”] 时,解析器就在内存上开辟一块存储空间放这个数组,而 x 就拿到了这个空间的地址(指针),再执行 x = [“ni”,”hao”] 时,解析器又新开辟一块存储空间放这个新数组,而x就是这个新存储空间的指针,这也就是说,JavaScript 里变量的重定义(或重新赋值)将会新开辟一块存储空间,而没有销毁原来的空间;回过头来再看例2,x[0] = “world”,这句没有给x新定义值,没有新开辟存储空间,只是修改了它存储空间里面的数据,因此例2最后alert出来的就是“world”;例1是字符串赋值,全过程是直接量操作。
这里主要是基本数据类型与引用数据类型的关系。
基本数据类型在内存中占有固定大小的空间,它们的值保存在栈内存中。
对于引用类型的值,是在堆内存中分配空间。但由于内存地址大小是固定的,因此内存地址保存在栈内存中,所以查询的时候先从栈内存中取到地址,然后在通过地址找到堆内存中的实际值。再看一个连续赋值的问题
引用http://www.iteye.com/topic/785445
var a = {n:1};
var b = a; // 持有a,以回查
a.x = a = {n:2};
alert(a.x);// --> undefined
alert(b.x);// --> [object Object]
发现a.x仍然是undefined,神奇的是 b.x 并未被赋值过(比如:b.x={n:2}),却变成了[object Object]。b 是指向 a({n:1})的,只有a.x = {n:2}执行了才说明b是有x属性的。实际执行过程:从右到左,a 先被赋值为{n:2},随后a.x被赋值{n:2}。
1, a = {n:2};
2, a.x = {n:2};
等价于
a.x = (a = {n:2});
注意,这个过程中a.x 中的a指向的是 {n:1},a 指向的是 {n:2}
最后附上另一道连续赋值问题
function fun(){
var a = b = 5;
}
fun();
alert(typeof a); // --> undefined
alert(typeof b); // --> number
fun执行后,这里的 变量 b 溢出到fun外成为了全局变量
ECMAScript中所有的参数传递都是按照值传递的
这里说一个个人的理解,参数传递实际就是栈内存的复制,基本类型都是保存在栈内存中的,这个不难理解,引用类型的值在堆内存中,但是地址保存在栈内存中,参数传递的时候复制了一个地址,也就相当于C中的指针,所以剩下的操作就可以理解为对指针的操作。