百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

JavaScript 基本数据类型和引用类型的区别详解

zhezhongyun 2024-12-03 06:30 62 浏览



js基本数据类型:

js基本数据类型包括:undefined,null,number,boolean,string.基本数据类型是按值访问的,就是说我们可以操作保存在变量中的实际的值

1. 基本数据类型的值是不可变的

任何方法都无法改变一个基本类型的值,比如一个字符串:

var name = "change";
name.substr();//hang
console.log(name);//change
var s = "hello";s.toUpperCase()//HELLO;
console.log(s)//hello

通过这两个例子,我们会发现原先定义的变量name的值始终没有发生改变,而调用substr()和toUpperCase()方法后返回的是一个新的字符串,跟原先定义的变量name并没有关系

或许有人会有以下的疑问,看代码:

var name = "change";
name = "change1";
console.log(name)//change1

这样看起来name的值“改变了”其实,var name = “change”,这里的基础类型是string,也就是”change”,这里的”change”是不可以改变的,name只是指向”change”的一个指针,指针的指向可以改变,所以你可以name = “change1″.此时name指向了”change1″,同理,这里的”change1″同样不可以改变

也就是说这里你认为的改变只是“指针的指向改变”

这里的基础类型指的是”change”,而不是name,要区分清楚

2. 基本数据类型不可以添加属性和方法

var p = "change";
p.age = 29;
p.method = function(){console.log(name)};
console.log(p.age)//undefined
console.log(p.method)//undefined

通过上面的代码,我们知道不能给基本类型添加属性和方法,也再次说明基本类型是不可变的

3. 基本数据类型的赋值是简单赋值

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

var a = 10;
var b = a;a++;
console.log(a)//11
console.log(b)//10

上面的代码中,a中保存的值是10.当使用a的值来初始化b时,b中也保存了值10.但b中的10和a中的10是完全独立的.b中的值知识a中值的一个副本.所以这两个变量可以参与任何操作而不会相互影响.如下图:

4. 基本数据类型的比较是值的比较

var person1 = '{}';
var person2 = '{}';
console.log(person1 == person2); // true

5. 基本数据类型是存放在栈区的

假如有以下几个基本类型的变量:

var name = "jozo";
var city = "guangzhou";
var age = 22;

那么它的存储结构如下图:

栈区包括了变量的标识符和变量的值

js引用类型:

js中除了上面的基本类型之外就是引用类型了,也可以说就是对象了,比如:Object,Array,Function,Data等

1. 引用类型的值是可以改变的

var o = {x:1};
o.x = 2;//通过修改对象属性值更改对象
o.y = 3;再次更改对象,给它增加一个属性
var a = [1,2,3];
a[0] = 0;//更改数组的一个元素
a[3] = 4;//给数组增加一个元素

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

var person = {};
person.name = "change";
person.say = function(){alert("hello");}
console.log(person.name)//change
console.log(person.say)//
function(){alert("hello");}

3. 引用类型的赋值是对象引用

先看以下代码:

var a = {};var b= a;
a.name = "change";
console.log(a.name)//change;
console.log(b.name)//change
b.age = 29;console.log(a.age)//29
console.log(b.age)//29

当从一个变量向另一个变量赋值引用类型的值时,同样也会将储存在变量中的对象的值复制一份放到为新变量分配的空间中.引用类型保存在变量中的是对象在堆内存中的地址,所以,与基本数据类型的简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象.那么赋值操作后,两个变量都保存了同一个对象地址,而这两个地址指向了同一个对象.因此,改变其中任何一个变量,都会互相影响

他们的关系如下图:

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

4. 引用类型的比较是引用的比较

var person1 = {};
var person2 = {};
console.log(person1 == person2)//false

为什么两个对象看起来一模一样,但是却不相等呢?

因为引用类型的比较是引用的比较,换句话说,就是比较两个对象保存在栈区的指向堆内存的地址是否相同,此时,虽然p1和p2看起来都是一个”{}”,但是他们保存在栈区中的指向堆内存的地址却是不同的,所以两个对象不相等

5. 引用类型是同时保存在栈区和堆区中的

引用类型的存储需要在内存的栈区和堆区共同完成,栈区保存变量标识符和指向堆内存的地址

假如有以下几个对象:

var person1 = {name:"change1"};
var person2 = {name:"change2"};
var person3 = {name:"change3"};

则这三个对象在内存中保存的情况如下图:

基本包装类型(包装对象):

先看下以下代码:

var s1 = "helloworld";
var s2 = s1.substr(4);

上面我们说到字符串是基本数据类型,不应该有方法,那为什么这里s1可以调用substr()呢?

通过翻阅js权威指南第3.6章节和高级程序设计第5.6章节我们得知,ECMAScript还提供了三个特殊的引用类型Boolean,String,Number.我们称这三个特殊的引用类型为基本包装类型,也叫包装对象.

也就是说当读取string,boolean和number这三个基本数据类型的时候,后台就会创建一个对应的基本包装类型对象,从而让我们能够调用一些方法来操作这些数据.

所以当第二行代码访问s1的时候,后台会自动完成下列操作:

  • 创建String类型的一个实例;// var s1 = new String(“helloworld”);
  • 在实例上调用指定方法;// var s2 = s1.substr(4);
  • 销毁这个实例;// s1 = null;

正因为有第三步这个销毁的动作,所以你应该能够明白为什么基本数据类型不可以添加属性和方法,这也正是基本装包类型和引用类型主要区别:对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都是一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。

相关推荐

perl基础——循环控制_principle循环

在编程中,我们往往需要进行不同情况的判断,选择,重复操作。这些时候我们需要对简单语句来添加循环控制变量或者命令。if/unless我们需要在满足特定条件下再执行的语句,可以通过if/unle...

CHAPTER 2 The Antechamber of M de Treville 第二章 特雷维尔先生的前厅

CHAPTER1TheThreePresentsofD'ArtagnantheElderCHAPTER2TheAntechamber...

CHAPTER 5 The King'S Musketeers and the Cardinal'S Guards 第五章 国王的火枪手和红衣主教的卫士

CHAPTER3TheAudienceCHAPTER5TheKing'SMusketeersandtheCardinal'SGuard...

CHAPTER 3 The Audience 第三章 接见

CHAPTER3TheAudienceCHAPTER3TheAudience第三章接见M.DeTrévillewasatt...

别搞印象流!数据说明谁才是外线防守第一人!

来源:Reddit译者:@assholeeric编辑:伯伦WhoarethebestperimeterdefendersintheNBA?Here'sagraphofStea...

V-Day commemorations prove anti-China claims hollow

People'sLiberationArmyhonorguardstakepartinthemilitaryparademarkingthe80thanniversary...

EasyPoi使用_easypoi api

EasyPoi的主要特点:1.设计精巧,使用简单2.接口丰富,扩展简单3.默认值多,writelessdomore4.springmvc支持,web导出可以简单明了使用1.easypoi...

关于Oracle数据库12c 新特性总结_oracle数据库12514

概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...

【开发者成长】JAVA 线上故障排查完整套路!

线上故障主要会包括CPU、磁盘、内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍。同时例如jstack、jmap等工具也是不囿于一个方面的问题...

使用 Python 向多个地址发送电子邮件

在本文中,我们将演示如何使用Python编程语言向使用不同电子邮件地址的不同收件人发送电子邮件。具体来说,我们将向许多不同的人发送电子邮件。使用Python向多个地址发送电子邮件Python...

提高工作效率的--Linux常用命令,能够决解95%以上的问题

点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...

linux常用系统命令_linux操作系统常用命令

系统信息arch显示机器的处理器架构dmidecode-q显示硬件系统部件-(SMBIOS/DMI)hdparm-i/dev/hda罗列一个磁盘的架构特性hdparm-tT/dev/s...

小白入门必知必会-PostgreSQL-15.2源码编译安装

一PostgreSQL编译安装1.1下载源码包在PostgreSQL官方主页https://www.postgresql.org/ftp/source/下载区选择所需格式的源码包下载。cd/we...

Linux操作系统之常用命令_linux系统常用命令详解

Linux操作系统一、常用命令1.系统(1)系统信息arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本dmidecode-q显示硬件系...

linux网络命名空间简介_linux 网络相关命令

此篇会以例子的方式介绍下linux网络命名空间。此例中会创建两个networknamespace:nsa、nsb,一个网桥bridge0,nsa、nsb中添加网络设备veth,网络设备间...