首页 > 代码库 > js按值传递和按引用传递
js按值传递和按引用传递
摘要:js的数据类型有种划分方式为 原始数据类型和 引用数据类型。
原始数据类型 存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。栈区包括了 变量的标识符和变量的值。
引用数据类型 存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。放在栈空间中的值是该对象存储在堆中的地址。
按值传递 VS. 按引用传递
按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低。两种传值方式都有各自的问题。
demo实例
typeof 运算符,返回一个字符串,
指示未经
计算的操作数的类型。
var person,name; person = ‘kn‘; name=person; person=‘黑白‘; console.log(person,name,typeof person)//黑白 kn string
person的改变没有改变name,说明 string 是按值传递的。赋值时创建一块新的内存空间
1、基本类型
- Boolean. 布尔值,
true
和false
. - null. 一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此
null
与Null
、NULL
或其他变量完全不同。 - undefined. 变量未定义时的属性。
- Number. 表示数字,例如:
42
或者3.14159。
- String. 表示字符串,例如:"Howdy"
- Symbol ( 在 ECMAScript 6 中新添加的类型).。一种数据类型,它的实例是唯一且不可改变的。
不可变(immutable)性质
基本类型是不可变的(immutable),只有对象是可变的(mutable). 有时我们会尝试“改变”字符串的内容,但在JS中,任何看似对string值的”修改”操作,实际都是创建新的string值。任何方法都无法改变一个基本类型的值, (疑问?重新赋值是在栈内存中创建一个新的内存,还是替换原来的内容)
1 var str = "abc"; 2 str[0]; // "a" 3 str[0] = "d"; 4 console.log(str); //abc 5 6 var name = ‘jozo‘; 7 var upName=name.toUpperCase(); 8 console.log(upName,name); // 输出 ‘JOZO‘ ‘jozo‘
方法操作无法改变一个基本类型的值
1 var person = ‘kn‘; 2 person.age = 24; 3 person.method = function(){}; 4 5 console.log(person.age); // undefined 6 console.log(person.method); // undefined
上面代码可知,我们不能给基本类型添加属性和方法
2.引用类型
引用类型的值是可变的
1 var obj = {x : 0}; 2 obj.x = 100; 3 var o = obj; 4 o.x = 1; 5 console.log(obj.x)// 1, 被修改 6 o = {x:100}; //等同于重新赋值,重新开辟内存,不是修改 7 console.log(JSON.stringify(obj),JSON.stringify(o))//{"x":1} {"x":100} 8 obj.x; // 1, 不会因o = {"x":100}改变
引用类型的值是同时保存在栈内存和堆内存中的对象
javascript和其他语言不同,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,那我们操作啥呢? 实际上,是操作对象的引用,
所以引用类型的值是按引用访问的。
准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,
也可以说是该对象在堆内存的地址。
假如有以下几个对象:
var person1 = {name:‘jozo‘};
var person2 = {name:‘xiaom‘};
var person3 = {name:‘xiaoq‘};
则这三个对象的在内存中保存的情况如下图:
var person1 = {}; var person2 = {}; console.log(person1 == person2); // false
引用类型时按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同,那很明显,person1和person2在堆内存中地址是不同的。
js按值传递和按引用传递