Fork me on GitHub

js中值类型和引用类型的区别

做个笔记免得忘了,方便查看

1.ECMAScript中有五种简单数据类型(也成为基本数据类型):String,Number,Boolean,Undefined,Null。还有一种复杂数据类型:Object(本质上是由一组无序的名值对组成),但是ECMAScript2016又新增了一种基本数据类型:symbol。

2. javascript中变量类型分为值类型(基本数据类型)和引用类型

  (1) 值类型:String(字符串),Number(数值),Boolean(布尔值),Undefined,Null(这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值)

  (2) 引用类型:Array(数组),Object(对象),Function(函数)(使用new()方法构造的对象)

3. 值类型和引用类型的区别

  (1) 存储位置不同

    ① 值类型的变量保存在栈中,占用空间固定,当一个函数执行时,每个函数都会建立自己的内存栈,在这个函数中声明的变量将会逐个放入这块栈内存里,随着函数的执行结束,这个函数的内存栈将被销毁,那么声明的变量也会自动销毁。因此,所有在函数中声明的变量都是放在栈内存中的。(栈中存储的是基础变量以及一些对象的引用变量,基础变量的值存贮在栈中,而引用变量存储在栈中的是指向堆中的数组或对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。

    ② 引用类型的变量名会保存在栈中,但是变量值会存储在堆中,占用空间不固定,当在程序中创建一个对象时,这个对象将被保存到运行时数据区中即堆内存中,以便反复利用(因为对象的创建成本通常比较大)。堆内存中的对象不会随方法的结束而自动销毁,因为即便方法结束后,这个对象还有可能被另一个引用变量所引用(方法的参数传递时很常见),所以这个对象不会被销毁。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

    

 

 

  (2) 复制方式不同

    ① 值类型保存与复制的是值本身,值类型的变量直接赋值就是深复制,如 

    

    ② 引用类型保存与复制的是指向对象的一个指针,引用类型的变量直接赋值实际上是传递引用,只是浅复制,值保存在内存中,而JS是不能直接访问内存的,所以对于引用类型,操作的不是实际的对象而是对象的引用。

      输出结果a.money和b.money都会是300,要想实现深复制,必须在堆内存中再开辟一块空间

  (3)数据类型检测不同

       ① 值类型使用typeof检测数据的类型;

       ② 引用类型使用instanceof检测数据类型;

  

 

 

  (4)引用类型可添加属性和方法

    ① 值类型无法添加属性和方法,如

    

    ②  引用类型可以添加属性和方法

    

  (5) 值之间的比较方式不同

    ①值类型的比较是值的比较,只有当它们的值相等的时候它们才相等。比较的时候注意”==”和”===”,双等号(==)在做比较的时候做了类型转换,而全等号(===)是值和类型相等是才能相等

      两个相同字符串的比较,是值(‘{}’)的比较,完全相等

    ② 引用类型的比较是引用地址的比较

       两个空对象在堆内存中的地址不一样,所以即使两个一模一样的对象也不一定相等,而a3和a1他们的指针是指向堆内存的同一个地址的所以输出true。

   (6) 传递参数不同

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

    

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

    

      

       对比两图代码会发现person对象的name属性值均为"Eve",如果 person 是按引用传递的,那么 person 就会自动被修改为指向其 name 属性值为"dorola"的新对象。但是,可以看到接下来再访问 person.name 时,显示的值仍然是"Eve",所以说对象是按值传递的。

    这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写 obj 时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。

4.变量计算--强制类型转换

 

 

 ok,完结!!

posted @ 2020-03-27 21:53  ID-矢量Nia呀  阅读(610)  评论(0)    收藏  举报