我在书上看,说基本类型是按值访问的,引用类型类型是按引用访问的,但是好像在某些操作的时候,引用类型也是按值访问的。按值访问和按引用访问有什么区别吗?
准确的说,JavaScript是按共享传递的(call by sharing)。
对于基本类型,按共享传递与按值传递(call by value)无异,你可以理解为JavaScript基本类型是按值传递的。
例:
var a = 1; function foo(x) { x = 2; } foo(a); console.log(a); // 1, 未受x = 2赋值所影响
而对于对象,较为特殊。我们可以修改对象中的属性,而变量的值是对象的引用,例如:
var obj = {x : 1}; function foo(o) { o.x = 3; } foo(obj); console.log(obj.x); // 3, 被修改了
但与按引用传递不同,修改形参o并不会影响obj.
var obj = {x : 1}; function foo(o) { o = 100; } foo(obj); console.log(obj.x); // 1, 不会被o = 100影响
为什么叫“按共享传递”呢?JavaScript的类型中,基本类型是不可变的(immutable),只有对象是可变的(mutable).
例如数字值100, 布尔值true, false,修改这些值并没有什么意义。比较容易误解的,是JavaScript中的string。但实际string值也是不可变的,例如:
var str = "string"; str.substring(5); // "g"
在JavaScript中,任何看似对string值的"修改"操作,实际都是创建新的string值。
而对象就不一样了,对象值是可变的。
var obj = {x : 1}; obj.x = 100; var o = obj; o.x = 1; obj.x; // 1, 被修改 o = true; obj.x; // 1, 不会因o = true改变
例如这里定义变量obj,值是object,然后设置obj.x属性为100。而后定义另一个变量,值仍然是这个object对象,此时obj和o两个变量的值指向同一个对象(共享同一个对象的引用)。所以修改这个可变的对象,对obj和o都有影响,但修改obj变量的值(不再指向这个对象),不会影响到o。
所以这里既不是按值传递,也不是按引用传递。而是按共享传递。
参考资料:http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value
整理了一篇更详细的文章:http://bosn.me/articles/js-call-by-sharing/
http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/
var obj = {x : 1}; obj.x = 100; var o = obj; o.x = 1; obj.x; // 1, 被修改 o = true; //o放弃和obj共享x : 1},去拥有true这个对象 typeof(o) boolean
回答的真好!