【JavaScript】基本数据类型与引用数据类型区别(及为什么String、Boolean、Number基本数据类型会有属性和方法?)

本文主要是介绍【JavaScript】基本数据类型与引用数据类型区别(及为什么String、Boolean、Number基本数据类型会有属性和方法?),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基本数据类型

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

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

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

var name = "change";
name.substr();//hang
console.log(name);//changevar 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″同样不可以改变。也就是说这里你认为的改变只是“指针的指向改变”


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;

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


引用数据类型

  JavaScript中除了基本数据类型外就是引用数据类型了(也可以说是对象)。比如: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()呢?

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

通过字面量的方式创建:var a = “String”; 这时它是基本数据类型;
通过构造函数的方式创建:var a = new String(“String”); 这时它是对 象类型。

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

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

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

  正因为有第三步这个销毁的动作,所以你应该能够明白为什么基本数据类型不可以添加属性和方法,这也正是基本包装类型和引用类型主要区别:对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都是一直保存在内存中.而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁(说的详细一点就是,JS引擎通过在内部临时创建一个对应的包装类型的临时对象,并把对基本类型的操作代理到这个临时对象身上,使得对基本类型的属性访问看起来像对象一样。但是在操作完成后,临时对象就扔掉了,下次再访问时,会重新建立临时对象,当然对之前的临时对象的修改都不会有效。)。

这篇关于【JavaScript】基本数据类型与引用数据类型区别(及为什么String、Boolean、Number基本数据类型会有属性和方法?)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146422

相关文章

如何解决Spring MVC中响应乱码问题

《如何解决SpringMVC中响应乱码问题》:本文主要介绍如何解决SpringMVC中响应乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC最新响应中乱码解决方式以前的解决办法这是比较通用的一种方法总结Spring MVC最新响应中乱码解

Java报NoClassDefFoundError异常的原因及解决

《Java报NoClassDefFoundError异常的原因及解决》在Java开发过程中,java.lang.NoClassDefFoundError是一个令人头疼的运行时错误,本文将深入探讨这一问... 目录一、问题分析二、报错原因三、解决思路四、常见场景及原因五、深入解决思路六、预http://www

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

Java常用注解扩展对比举例详解

《Java常用注解扩展对比举例详解》:本文主要介绍Java常用注解扩展对比的相关资料,提供了丰富的代码示例,并总结了最佳实践建议,帮助开发者更好地理解和应用这些注解,需要的朋友可以参考下... 目录一、@Controller 与 @RestController 对比二、使用 @Data 与 不使用 @Dat

python中字符串拼接的几种方法及优缺点对比详解

《python中字符串拼接的几种方法及优缺点对比详解》在Python中,字符串拼接是常见的操作,Python提供了多种方法来拼接字符串,每种方法有其优缺点和适用场景,以下是几种常见的字符串拼接方法,需... 目录1. 使用 + 运算符示例:优缺点:2. 使用&nbsjsp;join() 方法示例:优缺点:3

java streamfilter list 过滤的实现

《javastreamfilterlist过滤的实现》JavaStreamAPI中的filter方法是过滤List集合中元素的一个强大工具,可以轻松地根据自定义条件筛选出符合要求的元素,本文就来... 目录1. 创建一个示例List2. 使用Stream的filter方法进行过滤3. 自定义过滤条件1. 定

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

Java强制转化示例代码详解

《Java强制转化示例代码详解》:本文主要介绍Java编程语言中的类型转换,包括基本类型之间的强制类型转换和引用类型的强制类型转换,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录引入基本类型强制转换1.数字之间2.数字字符之间引入引用类型的强制转换总结引入在Java编程语言中,类型转换(无论