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


基本理解

  • 引用类型是一种用于将数据和功能组织在一起的数据结构(也常被成为类),引用类型的值(对象)是引用类型的一个实例。
  • 但是js中没有类的概念,因此引用类型也可以被称为对象定义,因为他们描述的是一类对象所具有的属性和方法。
  • 对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建的,构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。
  • ECMAScript提供了很多原生引用类型(如:Object),以便开发人员用以实现常见的计算任务

js原生引用类型

Object类型

我们看到的大部分引用类型都是Object类型的实例,Object的实例本身不具备很多功能,单对于在应用程序中存储和传输数据而言,是非常理想的选择。

Array类型

除了Object之外,Array算是js最常用最常用的类型。js中的数组与其他语言的数组都是数据的有序列表,但是,数组的每一项可以保存任何类型的数据

Date类型

js中用于构建日期对象的引用类型

RegExp类型

js通过RegExp类型来支持正则表达式

Function类型

js中的函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。如:

function sum(num1,num2){
    return num1 + num2;
} 

这与使用函数表达式定义函数的方法几乎相差无几:

var sum = function(num1,num2){
return num1 + num2;
}

JS值类型

值类型(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null

值类型和引用类型的区别

JS中的值类型的值是不可变的

任何方法都无法改变值类型的值。数字、布尔值、null和undefined等都属于不可变类型。比如,修改一个数值的内容,本身就说不通。虽然字符串可以被看成是由字符组成的数组,可能会被认为是可变的。但是,在JavaScript中,字符串是不可变的。在实际操作过程中,可以访问字符串任意位置的文本,单JavaScript并未提供修改已知字符串的文本内容的方法。

var str = 'abcdef';
console.log(str.toUpperCase()); // ABCDEF
console.log(str); // abcdef

可见,原始的str字符串值并未发生改变,仍然是小写的abcdef,第二行代码,只是调用了字符串的toUpperCase()方法后,返回的是一个新的字符串。

JS中的引用类型的值是可变的

var student = {name: '张三', age: 26};
console.log(student.name); // 张三
student.name = '李四'; 
console.log(student.name); // 李四

疑问:如果像studen.name = '李四’这段代码一样,给str也做相同的操作,str的值不也是改变了吗?

扩展:如果给str重新赋值,那么改变的是变量的值,给str重新赋值了,并没有改变字符串内容,改变的只是变量str的内容

JS中的值类型无法添加属性和方法

var student = '张三';
student.age = 26;
student.run = function () {
    console.log('跑步中...');
} 
console.log(student.age); // undefined 
console.log(student.run); // undefined

通过代码示例,可知,不能给值类型添加属性和方法。从而,也更加说明了值类型是不可变的。

JS中的引用类型可以添加属性和方法

var student = {};
student.age = 26;
student.run = function () {
    console.log('跑步中...');
}
console.log(student.age); // 26
console.log(student.run);
/*
function () {
    console.log('跑步中...');
}
*/

JS中的值类型的变量是存放在栈区的

JavaScript中的值类型的变量存储结构如下表模拟所示,栈区中包括了变量的标识符以及变量所对应的值。
在这里插入图片描述

JavaScript中的引用类型的变量也是存放在栈区的,不同的是,引用类型在栈区中存放的是变量标识符以及变量所对应值得引用地址,而变量所对应的值被存放在堆区中:
在这里插入图片描述

所以,可以看出,即使两个对象完全一样,但是在堆区中的存放地址是不一样的,所以在比较时,是不相等的。

JavaScript中的值类型的比较是值的比较:

JavaScript中的值类型在进行比较的时候,只有在它们的值相等的时候,它们才相等。注意:比较的时候注意“ == ”和“ === ”,双等号( == )在做比较的时候,做了类型转换,而全等号( === )是值和类型的比较,只有值和类型同时相等时,才能相等。

var student1 = '{}';
 
var student2 = '{}';
 
console.log(student1 === student2); // true
两个相同字符串的比较,是值(‘{}’)的比较,完全相等。

JavaScript中的引用类型的比较是引用地址的比较:

代码:

var student1 = {};
 
var student2 = {};
 
console.log(student1 === student2); // false

可见,两个空对象并不相等。

疑问:为什么两个一模一样的对象不相等呢?

扩展:因为引用类型是按引用地址访问的,引用类型的比较其实就是比较两个对象在堆内存中的地址是否相同,那么,很明显,student1和student2在堆内存中地址是不同的,所以,即使看到一模一样的两个对象,也不一定相等。

JavaScript中的值的变量赋值,是值得复制

JavaScript中的值类型的变量赋值过程中,在从一个变量到另一个变量赋值基本类型(值类型)时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上:

代码:

var str1 = 'abcdef';
 
var str2 = str1;
 
str1 = 'abc';
 
console.log(str1); // abc
 
console.log(str2); // abcdef

从上述代码示例中可以看出,str1中保存的值为 abcdef ,当使用 str1 来初始化 str2 时,str2 中保存的值也为abcdef,但str2中的值和str1中的值是完全独立的,str2的值只是str1中的值的一个副本,接下来,这两个变量可以参加任何操作而相互不影响。其实就是说,基本类型的变量在赋值操作后,两个变量是相互独立的,都不受影响的。

在这里插入图片描述

JavaScript中的引用类型的变量赋值过程中,在从一个变量到另一个变量赋值引用类型时,同样也会在该变量上创建一个新“值”,然后再把该“值”复制到为新变量分配的位置上。不同的是,复制的不是真正的“值”,而是真正的值在堆区中的存放地址:

var student1 = {age: 26};
 
var student2 = student1;
 
student2.age = 100;
 
console.log(student1.age); // 100
 
console.log(student2.age); // 100
 
console.log(student2 === student1); // true

引用类型的赋值其实是对象保存在栈区地址指针的赋值,两个变量都保存了同一个对象地址,则这两个变量指向了同一个对象。因此,改变其中任何一个变量,都会相互影响。

在这里插入图片描述

转载来源https://www.cnblogs.com/webhome/p/6434067.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值