05. JS 数据类型

一、相关概念

  • typeof 操作符

二、 基本数据类型

  • undefined 类型
  • null 类型
  • Boolen 类型
  • Number 类型
  • String 类型

三、基本数据类型转换

四、基本类型与引用类型的区别

五、基本包装类型和引用类型

一、相关概念

数据类型:

  • 基本数据类型(原始值):
    • NumberStringBoolNullUndefined

    • 按照值访问的,因为可以操作保存在变量中的实际值

    • 不能给基本类型的值添加属性

  • 引用数据类型(引用值):
    • Object(比如对象、数组、RegExp、Date…)

    • 按引用去访问:JS 和其他语言不同,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,那我们操作啥呢? 实际上,是操作对象的引用,
      所以引用类型的值是按引用访问的

    • 可以为其添加属性和方法,也可以改变和删除其属性和方法

typeof 操作符:

  • 鉴于 JavaScript 是松散类型的,故需要一种方法来检测给定变量的数据类型

    • undefined —— 值未定义
    • bool —— 布尔值
    • string —— 字符串
    • number —— 数值
    • object —— 对象或null
    • function —— 函数
  • typeof 操作符的操作数可以是变量,也可以是数值字面量

  • typeof 是一个操作符而不是函数,因此圆括号尽管可以使用,但不是必须的(推荐使用括号)

  • typeof(Number、Boolean、String、Undefined、Null、NaN)返回的值,类型都是string

typeof "John"      // 返回 string
typeof(NaN)         // 返回 number
typeof({1,2,3,4})   // 返回 object
typeof(null)        // 返回 object

function test(){
    console.log(typeof(arguments));
}

test();     // object // arguments 是类数组还是对象

二、基本数据类型详解

1. Undefined 类型

  • 使用 var 声明变量但未初始化时,这个变量的值就是undefined
var message;//这个变量声明之后默认取得了undefined值
alert(message==undefined);//true
alert(age);//产生错误

2. Null 类型

  • null 值表示一个空对象指针

  • 如果定义的变量准备将来用于保存对象,最好将变量初始化为 null 而不是其他值

  • 实际上,undefined 值是派生自 null 值的 null==undefined //true

var car=null;
console.log(typeof car);//"object"

var person = null;  // 值为 null(空),但类型为对象
  • undefinednull 的区别(值相等,但是类型不等)
typeof undefined    // undefined
typeof null         // object
null === nudefined  // false
null == undefined   // true

3. Boolean 类型

  • 有两个字面值:truefalse

  • 要将一个值转换为其对应的 bool 值,可以调用函数 Boolan()

  • 各种数据类型及其对应的转化规则

数据类型转化为true的值转化为false的值
Booleantruefalse
String任何非空字符串""(空字符串)
Number任何非零数字值(包括无穷大)0和NaN
Object任何对象null
Undefined——undefined

4. Number 类型

(1) 用来表示整数和浮点数值
(2) 整数的表示方法
  • 十进制(0-9):在进行算数计算时,所有以八进制和十六进制表示的数值最终后将被转化成十进制数值

  • 八进制(0-7)

    • 第一位必须是零(0)

    • 然后后面是八进制数字序列

    • 八进制字面量在严格模式下是无效的,会导致支持该模式的JavaScript引擎抛出错误

    • var octalNum1=070; //八进制的56

  • 十六进制(0-9、A(a)-F(f)

    • 前两位必须是0x

    • 后跟任何十六进制数字(0-9及A-F、a-f)

    • var hexNum1=0xA; //十六进制的10

(3) 浮点数值相关概念
  • 定义:该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字

  • 小数点前可以没有数值,但不推荐这种写法

  • 由于保存浮点数值需要的内存空间是保存整数值的两倍,因此 ECMAScript 会将无意义的浮点数值转化为整数值

    • var floatNum1=1.;//解析为1

    • var floatNum2=10.0;//解析为10

(4) 浮点数值的表示
  • 极大或极小的数值,可以用ye表示(科学计数法)

  • [整数/浮点数]数值 e(E) 指数 --> var floatNum = 3.125e7;//31250000

  • 浮点数值的最高精度是17位小数,但在进行算术计算时其精度远远不如整数

  • 例如:0.10.2的结果不是0.3,而是0.30000000000000004。这个小小的舍入误差会导致无法测试特定的浮点数值

(5) 数值范围
  • 由于内存的限制,ECMAScript 并不能保存世界上所有的数值

  • 最小数值是5e-324(Number.MIN_VALUE),最大值是1.7976931348623157e+308(Number.MAX_VALUE)

  • 正无穷(Infinity),负无穷(-Infinity)

  • Infinity是不能参与计算的数值

  • isFinite()函数:在参数位于最小和最大数值之间时会返回true

(6) NaN
  • 即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(不会抛出错误)

  • 任何涉及NaN的操作都会返回NaN,这个特点在多步计算中有可能导致问题

  • NaN与任何值都不相等,包括NaN本身

  • isNaN()函数

    • 这个函数接收一个参数,该参数可以是任何类型,而函数可以帮我们确定这个参数是否“不是数值”

    • isNaN()在接收一个值以后,会尝试将这个值转化为数值

    • 任何不能被转化为数值的值都会导致这个函数返回true

console.log (isNaN(NaN));//true
console.log (isNaN(10));//false,数值10
console.log (isNaN("10"));//false,转化为10
console.log (isNaN("blue"));//true
console.log (isNaN(true));//true,转化为1

5. String类型

  • 字符串可以存储一系列字符,如 “John Doe”

  • 字符串可以由双引号(")或单引号(’)表示,两种字符串的写法都是有效的(最好是用单引号)

  • 字符串长度:length

    • var test ="This is the letter sigma"; console.log(test.length); //24
  • 你可以使用索引位置来访问字符串中的每个字符:

var carname = "Volvo XC60";
console.log(carname[4]);    // o
  • 可以在字符串中使用引号,字符串中的引号不要与字符串的引号相同

    • var answer = "He is called 'Johnny'";

    • var y = "He is called \"Johnny\""; // 反斜杠是转义符

  • 要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量

三、基本数据类型转换

1. 显式类型转换

(1) 转换为字符串:
  • toString(radix)

    • 数值、布尔值、对象和字符串值都有toString()方法

    • nullundefined值没有这个方法

    • 在调用数值的toString()方法时可以传递一个参数:输出数值的基数

  • String(mix) : 转换成字符串,一般都用这个来转换字符串。

    • 如果值是null,则返回"null"

    • 如果值是undefined,则返回"undefined"

var num = 10;
console.log(num.toString());    //'10'
console.log(num.toString(2));   //"1010" 
console.log(num.toString(8));   //"12" 
console.log(num.toString(10));  //"10" 
console.log(num.toString(16));  //"a" 
//默认的(没有参数的)输出值与指定基数10时的输出值相同

var value1=10;
var value2=true;
var value3=false;
var value4;
console.log(String(value1));//"10"
console.log(String(value2));//"true"
console.log(String(value3));//"null"
console.log(String(value4));//"undefined"
(2) 转换为数字:
  • number(mix):转换成数字,如果有无法转换的,最终结果就是 NaN

    • Boolean值:trufalse将分别被转换为10

    • 数字值:只是简单的传入和返回

    • null值:返回0

    • undefined:返回NaN

    • 字符串,遵循下列规则:

      • 如果字符串只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值。即"1"——>1,"123"——>123",011"——>11(前面的零被忽略了)

      • 如果字符串中包含有效的浮点格式,"1.1"——>1.1(也会忽略前面的零)

      • 如果字符串是空的(不包含任何字符),转换为0

      • 如果字符串包含上述格式之外的字符被,则转换为NaN

    • 对象,则调用valueOf()方法,然后按照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转化返回的字符串值

var num1=Number("Hello world!");//NaN
var num2=Number("");//0
var num3=Number("000111");//111
var num4=Number(true);//1
  • parseInt(string,radix) :转换成整数,radix 是基底的意思,范围是 2-36

    • 转换字符串时,看是否符合数值模式

    • 它会忽略字符串前面的空格,直到找到第一个非空格字符

    • 如果第一个不是数字字符或者负号,parseInt()会返回NaN

    • parseInt()转换空字符串或返回NaN

    • 如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到一个非数字字符

    • 例如:"1234blue"——>1234","22.5"——>22,小数点并不是有效的数字字符

    • parseInt()也能识别出各种整数格式(十进制、八进制和十六进制)

    • 在使用ECMAScript 3 JavaScript引擎中,"070"被当成八进制字面量,转换后是56;而在 ECMAScript 5 JavaScript引擎中,parseInt()已经不具有解析八进制值的能力,因此前导的零会被认为无效,转换为十进制70

    • 为了消除在使用parseInt()函数时可能导致的问题,可以提供第二个参数,转换时使用的基数(即多少进制)(代码示例下)

var num1=parseInt("1234blue");//1234
var num2=parseInt("");//NaN
var num3=parseInt("0xA");//10(十六进制数)
var num4=parseInt(22.5);//22
var num5=parseInt("070");//56(八进制数)
var num6=parseInt("70");//70(十进制数)
var num7=parseInt("0xf");//15(十六进制数)

var num =parseInt("0xAF",16);//175,按16进制解析
var num1=parseInt("AF",16);//175,如果指定了16作为第二个参数,字符串可以不带前面的"0x"
var num2=parseInt("AF");//NaN
  • parseFloat(string) :转换成浮点数

    • 从第一个字符(位置0)开始解析每个字符

    • 一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符位置

    • 字符串中的第一个小数点是有效的,第二个小数点是无效的,因此它后面的字符串将被忽略

    • 始终会忽略前导0

    • 十六进制格式的字符串始终会转换成为0

    • parseInt()只解析十进制值,因此它没有用第二个参数指定基数的用法

    • 如果字符串包含一个可解析为整数的数(没有小数点,或者小数点后都是零),会返回整数

var	num1 =parseFloat("1234blue");//1234(整数)
var	num2 =parseFloat("0xA");//0
var	num3 =parseFloat("22.5");//22.5
var	num4 =parseFloat("22.34.5");//22.34
var	num5 =parseFloat("0908.5");//908.5
var	num6 =parseFloat("3.125e7");//31250000
(3) + 运算符可以连接字符串,也可以将字符串转换为数字。
var n = '12ab';
var x = '34';
alert(n+x);    //返回:12ab34
alert(parseInt(n)+x);    //返回:1234

var y = + x;
alert(typeof x);    //返回:string
//若变量不能转换,但仍然是一个数字,NaN
alert(typeof y);    //返回:number
(4) NaN 的数据类型是 number,NaN 表示非数字(Not a Number),所以本身也为数字。
var a = parseInt('abc');
var b = parseInt('12edf');
var c = 12+NaN;
alert(c);    //返回NaN

//判断NaN是否等于NaN
alert(a==b);    //返回false

//isNaN判断一个变量是不是NaN
alert(isNaN(a));    //返回:true
alert(isNaN(b));    //返回:flase

2. 隐式类型转换

  • isNaN():括号里面进行显示类型转换 Number(),括号里的结果是 NaN 就返回 true,不是就返回 false
console.log(isNaN("abc"));
// true 
// number("abc") --> NaN 结果和 NaN 比对。
  • ++/--

    • ++或者-- 前先将变量进行显示类型转换 Number()
var a = "123"
a ++;   // number("123") -> 123
console.log(a);
// 124
  • - * / % : 两边都会进行 number()
var a = "3"*1;
console.log(a + " : " + typeof(a));
// 3 : number
  • && || !

  • < > <= >=

var a = "3" > 2;    //字符串转换成数字 -> 数字优先
console.log(a + " : " + typeof(a));
// true : boolean
  • ==
var a = "1" ; 		//string
var b = true ; 		//boolean

if(a == b){
	alert('相等');
} else {
	alert('不等');
} 
//相等

// == 表示 可以经过自动转换 比较的是数值 
// === 表示 可以经过自动转换 先比较值, 再比较数据类型

3. 不发生类型转换

  • === 绝对等于

  • !== 绝对不等于

四、基本类型与引用类型的区别

1. 基本类型

  • 基本类型的值是不可变得

  • 基本类型的比较是值的比较

  • 基本类型的变量是存放在栈区的(栈区指内存里的栈内存)

var name = 'jozo';
var city = 'guangzhou';
var age = 22;
栈区栈区
标识符变量的值
namejozo
cityguangzhou
age22

2. 引用类型(对象)

  • 引用类型的值是可变的:可以添加属性和方法,也可以删除其属性和方法
var person = {};//创建个空对象 --引用类型
person.name = 'jozo';
person.age = 22;
person.sayName = function(){console.log(person.name);} 
person.sayName();// 'jozo'
 
delete person.name; //删除person对象的name属性
person.sayName(); // undefined
  • 引用类型的值是同时保存在栈内存和堆内存中的对象

    • 引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,
      也可以说是该对象在堆内存的地址
var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};
栈区栈区----->堆区
person1堆内存地址1----->object1
person2堆内存地址2----->object2
person3堆内存地址3----->object3
  • 引用类型的比较是引用的比较
var person1 = {};
var person2 = {};
console.log(person1 == person2); // false
// 比较两个对象的堆内存中的地址是否相同,那很明显,person1 和 person2 在堆内存中地址是不同
栈区栈区----->堆区
person1堆内存地址1----->{}
person2堆内存地址2----->{}

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中的是完全独立的,该值只是a中的值的一个副本
//此后,这两个变量可以参加任何操作而相互不受影响。
  • 也就是说基本类型在赋值操作后,两个变量是相互不受影响的。

4. 对象引用

  • 当从一个变量向另一个变量赋值引用类型的值时,同样也会将存储在变量中的对象的值复制一份放到为新变量分配的空间中

  • 与简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象

  • 那么赋值操作后,
    两个变量都保存了同一个对象地址,则这两个变量指向了同一个对象。因此,改变其中任何一个变量,都会相互影响

var a = {}; // a保存了一个空对象的实例
var b = a;  // a和b都指向了这个空对象
 
a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'
 
b.age = 22;
console.log(b.age);// 22
console.log(a.age);// 22
 
console.log(a == b);// true

五、基本包装类型和引用类型

1. 相关概念

  • 为了便于操作基本类型值,JS 提供了三个特殊的引用类型:BooleanNumberString。这些类型与其他引用类型相似,但同时也具有与各自基本类型相应的特殊行为

  • 实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法操作这些数据

var s1="some text";
var s2=s1.substring(2);
//变量s1包含一个字符串,字符串是基本类型值。下一行调用了s1的substring()方法,并将返回结果保存到了s2中
//基本类型值不是对象,因此逻辑上不应该有方法。其实,为了实现这种直观的操作,后台已经自动完成了一系列的处理。
//当第二行代码访问s1时,访问过称出于一种读取模式,也就是要从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成下列处理
/*
(1)创建String类型的一个实例
(2)在实例上调用指定的方法
(3)销毁这个实例
var s1=new String("some text");
var s2=s1.substring(2);
s1=null;
//经过这些处理,基本的字符串值就变得和对象一样了。而且,上面的三个步骤也适用Boolean和Number类型对应的布尔值和数字值
*/

2. 区别

  • 引用类型与基本包装类型的主要区别就是对象的生存期

  • 使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中

  • 自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁

//这就意味着不能在运行时为基本类型值添加属性和方法
var s1="some text";
s1.color="red";
alert(s1.color);//undefined
//在此,第二行代码试图为字符串s1添加一个color属性。但是,当第三行代码在此访问s1时,其color属性没有了。
//因为第二行常见的String对象在执行第三行代码前就已经被销毁了。
//第三行又创建自己的String对象,而该对象没有color属性

3. 显示创建基本包装类型

  • 可以显示地调用BooleanNumberString来创建基本包装类型的对象

  • 应该在绝对必要的情况下在再这样做,因为这样会让人分不清自己是在处理基本类型还是引用类型的值

  • 对基本包装类型的实例调用typeof会返回 "Object",而所有基本包装类型的对象在转换为布尔值都是true

  • Object构造函数会将根据传入值的类型返回相应基本包装类型的实例

    • 把字符串传给Object构造函数,就会创建String的实例

    • 传入的数值参数会得到Number的实例

    • 传入布尔值就会得到Boolean的实例

var obj = new Object("some text");
console.log(obj instanceof String);//true
  • 使用new调用基本包装类型的构造函数

    • 使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的

    • 虽然不建议显示地创建基本包装类型的对象,但它们操作基本类型值的能力还是很重要的。而每个基本包装类型都提供了操作相应值的便捷方法

var value="25";
var number=Number(value);//"转型函数"
alert(typeof number);//"number"

var obj=new Number(value);//构造函数
alert(typeof obj);//"object"
//变量number中保存的是基本类型的值 25,而变量 obj 中保存的的是 Number 的实例
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值