JS中变量的区别(基本类型和引用类型的区别)和传参的区别

变量

基本类型和引用类型

基本类型:指的是简单的数据段
基本数据类型:Undefined,Null,Boolean,Number和String(5种基本数据类型)

引用类型:指那些可能有多个值构成的对象
引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象,为此,引用类型的的值是按引用访问的

基本类型和引用类型的区别

①动态的属性

对于引用类型的的值,我们可以为其添加属性和方法,也可以改变和删除去属性方方法,如下所示
var person = new Object(); 
person.name = "Nicholas"; 
alert(person.name); //"Nicholas"   为对象添加了一个name的属性并赋值为"Nicholas"
对于基本类型的值,我们为其赋值属性则输出的结果是undefind
var name = "Nicholas"; 
name.age = 27; 
alert(name.age); //undefined

②复制变量值

基本类型复制值:会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上

var num1 = 5; 
var num2 = num1; 

在此,num1 中保存的值是 5。当使用 num1 的值来初始化 num2 时,num2 中也保存了值 5。但 num2中的 5 与 num1 中的 5 是完全独立的,该值只是 num1 中 5 的一个副本。此后,这两个变量可以参与任何操作而不会相互影响
JS中变量的区别(基本类型和引用类型的区别)和传参的区别
引用类型的复制值:当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量

var obj1 = new Object(); 
var obj2 = obj1; 
obj1.name = "Nicholas"; 
alert(obj2.name); //"Nicholas"

首先,变量 obj1 保存了一个对象的新实例。然后,这个值被复制到了 obj2 中;换句话说,obj1和 obj2 都指向同一个对象。这样,当为 obj1 添加 name 属性后,可以通过 obj2 来访问这个属性,因为这两个变量引用的都是同一个对象。
JS中变量的区别(基本类型和引用类型的区别)和传参的区别

③传递参数

ECMAScript 中所有函数的参数都是按值传递的
也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样

在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript 的概念来说,就是 arguments 对象中的一个元素) arguments 表示参数的集合

在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部

传递参数,相当于传入基本类型和引用类型的值的复制的值,基本类型传入的是复制的基本类型的变量,在函数内修改参数不会对原本的变量产生影响,引用类型传入的是引用类型的指针,在函数内部修改参数,会对参数外部的引用类型的值产生影响

基本类型传参的示例:

function addTen(num) { 		
 num += 10; 
 return num; 
}
var count = 20; 		
var result = addTen(count);  	
alert(count);	 //20,没有变化
alert(result); //30

这里的函数 addTen()有一个参数 num,而参数实际上是函数的局部变量。在调用这个函数时,变量count作为参数被传递给函数,这个变量的值是20。于是,数值20被复制给参数num以便在addTen()中使用。在函数内部,参数 num 的值被加上了 10,但这一变化不会影响函数外部的 count 变量。参数num 与变量 count 互不相识,它们仅仅是具有相同的值。假如 num 是按引用传递的话,那么变量 count的值也将变成 30,从而反映函数内部的修改

引用类型传参示例:

function setName(obj) { 
 obj.name = "Nicholas"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"

以上代码中创建一个对象,并将其保存在了变量 person 中。然后,这个变量被传递到 setName()函数中之后就被复制给了 obj。在这个函数内部,obj 和 person 引用的是同一个对象。换句话说,即使这个变量是按值传递的,obj 也会按引用来访问同一个对象。于是,当在函数内部为 obj 添加 name属性后,函数外部的 person 也将有所反映;因为 person 指向的对象在堆内存中只有一个,而且是全局对象。有很多开发人员错误地认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的

function setName(obj) { 
 obj.name = "Nicholas"; 
 obj = new Object(); 
 obj.name = "Greg"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"

这个例子与前一个例子的唯一区别,就是在 setName()函数中添加了两行代码:一行代码为 obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的 name 属性。在把 person 传递给setName()后,其 name 属性被设为"Nicholas"。然后,又将一个新对象赋给变量 obj,同时将其 name属性设置为"Greg"。如果person 是按引用传递的,那么 person 就会自动被修改为指向其 name 属性值为"Greg"的新对象。但是,当接下来再访问 person.name 时,显示的值仍然是"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写 obj 时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。也就是说,操作的是对象实际的值 对这点概念不理解的,可以去看下我博客上转载的"JavaScript变量的访问方式(值&引用)详解"其实这个问题我野纠结了很久

如果对你有帮助,你可以点个赞对我支持一下,毕竟整理不易,谢谢!!