JS有哪些数据类型?它的特点和区别。栈和堆的是什么?数据类型之间的转换

大家好,我是IT修真院武汉分院web第17期的学员吴三水,一枚正直纯洁善良的web程序员
今天给大家分享一下,修真院官网js(职业)任务一,深度思考中的知识点——JS有哪些数据类型?

1.背景介绍

JS有哪些数据类型?

JS有哪些数据类型?它的特点和区别。栈和堆的是什么?数据类型之间的转换_第1张图片

JS中有两种数据类型

1.简单数据类型(也称基本数据类型):Undefined;Null;Boolean;Number和String。

2.引用数据类型(也称复杂数据类型),其中包括Object;Array;Function等等。

PS:在引用数据类型中,又有三个特殊的引用类型,和基本数据类型相似。

2.知识剖析

辨别数据

一般情况下我们可以用typeof()来辨别一些数据的类型

typeof ( 123 )   //Number
typeof ( 'abc' )  //String
typeof ( true ) //Boolean
typeof ( undefined ) //Undefined
typeof ( null ) //Object
typeof ( { } ) //Object
typeof ( [ ] ) //Object
typeof ( function (){} ) //Function

经过试验后发现,typeof虽然能够辨别出数据的类型,但是因为null、{}、[]都是算是一个空的对象,所以它返回的都是Object,typeof 返回值有6中类型: “number,” “string,” “boolean,” “object,” “function,” 和 “undefined.”。
PS:因此使用typeof()无法细致辨别出arry、null和object。

基本数据和引用数据的特点和区别

基本数据类型:

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

var s = "hello";
s.toUpperCase()//HELLO;
alert(s.toUpperCase())//HELLO;
alert(s)//hello

虽然s.toUpperCase()将hello改变为了HELLO,但是s的值没有变化,可得知:这里调用toUpperCase()方法后返回的只是一个新的字符串,跟原先定义的变量s并没有关系。

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

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

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

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

var a = 10;
var b = a;
a++;
alert(a)//11
alert(b)//10

上面的代码中,a中保存的值是10.当使用a的值来初始化b时, b中也保存了值10.但b中的10和a中的10是没有任何关联的。
b值中的10只是a值中的一个副本. 所以这a,b两个变量可以参与任何操作而不会相互影响。

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

var person1 = 'abc';
var person2 = 'abc';
alert(person1 == person2); // true;
var person1 = 'abc';
var person2 = 'abcd';
`alert(person1 == person2); // false;
var person1 = 1;
var person2 = true;
`alert(person1 == person2); // true;

从person1 和person2的3个对比,我可以发现,它们的数据对比是它们值的比较,而不是数据类型的比较。

引用数据类型
引用数据类型的特点和基本数据类型相反。

引用数据类型
引用类型的值是可以改变的
var a = [1,2,3];
a[0] = 0;//更改数组的一个元素
a[3] = 4;//给数组增加一个元素
alert(a);//0.2.3.4;

上面代码中可以看到,a的数组第一个1更改为了0,而且还添加一个a原来没有的第四个值4.我们可得知引用类型的值是可以改变的。

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

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

上面代码中可以得知,引用类型的数据可以给其添加属性和方法。

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

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

当从一个变量向另一个变量赋值引用类型的值时, 同样也会将储存在变量中对象的值复制一份放到为新变量分配的空间中. 因为引用类型保存在变量中的值是对象在堆内存中的地址(这个地址就是指向对象在堆内存里的指针),所以两个变量都保存了同一个对象的地址,而这两个地址指向了同一个对象,因此,对于这2个变量,我们改变任何一个变量,都会互相影响。

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

var person1 = {};
var person2 = {};
alert(person1 == person2)//false

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

3.常见问题

jAVAScirpt数据能否转换?

4.解决方案

js中的不同类型数据在运算过程中会自动进行转换。

我们先来看一串代码;

var str1 = "a";
var num1 = "1";
var bool1 = "true";
var bool2 = "false";
alert(str1 + num1);//string;
alert(str1 + bool1);//string;
alert(num1 + bool1);//number;
alert(bool1 + bool2);//number//

js运算时数据转换的运算规则为:
Number+String=String
数值和字符串相加等于字符串。
Number+Boolean=Number
数值和布尔值相加等于数值。
String+Boolean=String
字符串和布尔值相加等于字符串。
Boolean+Boolean=Number
布尔值和布尔值相加等于数值。

数组和其他类型的变量进行运算时都转化成string

数值和数组运算时
var arr=[1,2,3];
var a= "789";
alert(typeof(arr+a));
布尔值和数组运算时
var arr=[1,2,3];
var a= "true";
alert(typeof(arr+a))
对象和数组运算时
var arr=[1,2,3];
var a= {name:"my"}
alert(typeof(arr+a))

上面三组运算无一列外得到的结果都是string,证实了数组和其他类型的变量进行运算都会转化为string。

5.编码实战

6.拓展思考

栈,堆是什么?

在ECMAScript中,变量可以存放两种类型的值,即原始值和引用值。
原始值指的就是代表原始数据类型(基本数据类型)的值,
引用值指的就是复合数据类型(引用数据类型)的值。
原始值与引用值对应存在两种结构的内存即栈和堆
JS有哪些数据类型?它的特点和区别。栈和堆的是什么?数据类型之间的转换_第2张图片
栈是一种后进先出的数据结构。原始值是存储在栈中的简单数据,它们的值直接存储在变量访问的位置

JS有哪些数据类型?它的特点和区别。栈和堆的是什么?数据类型之间的转换_第3张图片
堆是基于散列算法的数据结构。
在javascript中,引用值是用来引用存储在堆中的对象,引用出来的对象是存放在堆中的。
也就是说,存储在变量处的值(即指向对象的变量,存储在栈中)是一个指针,指向存储在堆中的实际对象.

我看来下面这串代码

var obj = new Object();

obj存储在栈中,它指向于new Object()这个对象,
而new Object()是存放在堆中的。

7.参考文献

js的数据类型
引用类型与原始类型的区别
js常见问题总结(1)——数据类型相关
JavaScript基础心法 数据类型
8.更多思考

那为什么引用值要放在堆中,而原始值要放在栈中.

js中有一句话:能量是守衡的,无非是时间换空间,空间换时间的问题。

堆比栈大,栈比堆的运算速度快。
  引用数据类型是一个复杂的结构,并且可以自由扩展,如:数组 可以无限扩充,对象可以自由添加属性。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。
  相对于引用数据类型而言,简单数据类型就比较稳定,并且它只占据很小的内存。不将简单数据类型放在堆是因为通过引用到堆中查找实际对象是要花费时间的,而这个综合成本远大于直接从栈中取得实际值的成本。所以简单数据类型的值直接存放在栈中。

你可能感兴趣的:(javascript)