从0开始,一点一点学会JavaScript【连载中】

您所在的位置:网站首页 javascript主要数据类型 从0开始,一点一点学会JavaScript【连载中】

从0开始,一点一点学会JavaScript【连载中】

2022-11-11 01:37| 来源: 网络整理| 查看: 265

实时更新的进度:2022/10/22 15:49:35更新​​​

本文主要学习JavaScript高级程序设计(第4版)

在这里插入图片描述

1. 语法1.1 JavaScript的组成

完整的JavaScript由三部分组成:

ECMAScript(核心)

DOM(文档对象模型)

BOM(浏览器对象模型)

在这里插入图片描述

1.2 语法由谁定义

由ECMA-262以一个名为ECMAScript的伪语言定义了js的语法、标识符、数据类型等功能,ECMAScript只是一种规范,而JavaScript实现了ECMAScript

1.3 语法风格

ECMAScript的语法是一种宽松的语法,借鉴C语言和类C语言,如java

1.4 区分大小写

ECMAScript中的一切区分大小写,如变量,函数名,操作符等

1.5 标识符​

标识符:变量、函数、属性或者函数参数

其组成应遵循以下规则:

第一个字符必须是字母,下划线(_)或美元符号($)其他的可以是字母,下划线、美元符号和数字

也就是说:数字绝对不能做开头!!!

另外,字母可以是拓展ASCII码中的字母,也可以是Unicode的字母(不推荐使用中文做变量)

1.5.1 驼峰书写法

依照惯例,ECMAScript中的标识符建议以驼峰大小表示,即第一个字母首字母小写,后面几个字母首字母大写,如:

var apple; var appleNumber; var appleAndBananaNumber; 1.5.2 不是符合标识符规范的就能成为标识符

​️ 关键字、保留字、true,false,null都不能作为标识符

这是关于关键字、保留字进行介绍

1.6 注释

与C语言一样

单行注释:

//我是单行注释

多行注释:

/* 我是 多行 注释 */ 1.7 严格模式

ES5增加了严格模式(strict mode) 简单来说,他会对ES3不规范的一些写法会被处理,对不安全的活动抛出错误,使用该模式的目的就是为了保证ES3语法能够安全的运行。 它所带来的影响非常的大,初学者暂时只要知道其概念就可以了。

1.8 语句结尾

参照C和java,ECMAScript也要用 ; 结尾,注意这是一种规范,虽然不加也可以运行,但有可能在压缩的时候出现问题。

而且最为重要的一点是:加 ; 有时可以提升性能,因为解析器会在合适的位置补上分号来纠正语法错误,所以如果你一个分号不写,解释器会累死,得帮你加那么多个分号,当然性能会受到影响了。

console.log("关爱机器,记得分号"); 1.9 块

我们如果学过C语言,应该都知道,if这种条件控制语句,语句内部只有一条的时候,可以不用{}括起来,JS同样也是,例如:

if(true) var a = 1;

但是,️ 不推荐,这里涉及到块作用域的知识,在let关键字部分会详细讲解。 还是建议,无论多条还是单条语句都用{}括起来

if(true) { var a = 1; } if(true) { var b = 2; var c = 3; } 2. 关键字与保留字

ECMA-262描述了一组保留的关键字,这些关键字有特殊作用。比如开始循环,打破循环,函数的返回值等,所以为了避免语义的混乱,保留的关键字不能作为标识符和属性名。

大部分关键字如下:在这里插入图片描述

但规范也知道未雨绸缪,同时描述了一组未来的保留字(未来版本更新很有可能会升级为关键字),同样不能作为标识符和属性名。

主要也是为了版本的兼容性问题,如果我执意在当前版本中使用未来的保留字作标识符(假设操作可行),版本更新后,我的标识符与关键字产生了语义冲突,这时候修改起来就很麻烦,甚至带来经济损失。

所以,无论是现在的关键字也好,未来的保留字也罢,都不能作为标识符和属性名。

3.变量3.1 简述

ECMAScript变量是松散类型的,也就是说变量可以保存任何类型的数据。近几年很火的python也是这种类型的,而Java和C自然就不是了。

而变量的声明依靠3个关键字:

所有版本都可以用的varES6新出的let和const(既然是ES6出的,肯定就只能在ES6及之后的版本使用)

他们三个基本功能都差不多,所以这也是为什么很多教程一直都用var声明变量,实际上var这个关键词会带来很多问题,下面我们就来具体了解了解他们的区别。

3.2 var关键字3.2.1 定义

定义很简单:

var + 变量名; //例如 var people;

但需注意的是,像上面这样声明后不初始化,也就是没有给people一个具体的值,这时候如果直接打印people,那么得到的结果将是undefined(六大基本数据类型之一)

所以,建议:一定义,就给值

var people = "zuolun"; 3.2.2 改值

由于变量是松散类型,所以我可以更改变量里存在的值,这里依照我个人的理解可以分为两种情况:

改类型,虽然可行,但 ️不推荐var people = "zuolun"; people = 2; 改值,但不变类型,可行且推荐var people = "zuolun"; people = "zuolun7" 3.2.3 声明的作用域

var定义的变量会成为包着它的函数的局部变量,函数结束,变量被释放。

当把一个JavaScript文件交给JS引擎执行时,JS引擎就是从上到下逐条执行每条语句的,所以实际上JavaScript没有主函数main这个概念。

也就是说,如果没在函数和块里的语句实际上都在全局域中,所以如果在全局域中用var声明的变量,实际上他就是一个全局变量。 定义在函数内部的局部变量,外部无法访问但函数内部可以访问的栗子:

function hello(){ var x = 1; console.log(x); } hello(); console.log(x);

在这里插入图片描述 也就是说全局域访问函数变量,是不可行的,会抛出ReferenceError错误 但我如果一定要在函数内声明为全局变量,即函数外部能够访问到,可以怎么做呢? 可以去掉var,进行声明。但注意️,不推荐这么做,因为这样定义的全局变量很难维护,在严格模式下,会抛出ReferenceError。

function hello(){ x = 1; } hello(); console.log(x);

在这里插入图片描述

3.2.4 变量提升

var关键字会将函数内部变量声明提前到函数作用域的顶部,也就会出现这么一种现象,即未声明的变量可能操作的时候,不会报错,这就是提升。举个栗子

function hello(){ console.log(x); var x = 5; } hello();

在这里插入图片描述

从结果可以见得,x打印出来的undefined的类型。实际上一下函数可以等价下面这个过程:

function hello(){ var x;//变量声明提前 console.log(x); x = 5; } hello();

打印结果也是一样的。

3.2.5 反复声明

此外,使用var多次声明同一个变量也没有什么问题,按照程序运行顺序,后面定义的会覆盖前面定义的。

var x = 5; var x = 6; var x = 7; console.log(x);

该语句将输出7,结果也遵循程序的顺序执行。

3.3 let关键字3.3.1 定义

let与var的作用差不多,都可以用来声明变量。

但有个很明显的区别就是:let声明的范围是块作用域,而var声明的范围是函数作用域。

块作用域:{ }里面都算块作用域,其主要用于if条件控制,for循环,自定义块作用域上

if(true) { let x = 3; console.log(x); } console.log(x);

在这里插入图片描述 由结果我们可以见得:let在块中声明的变量,只在块中起作用,全局域中不起作用。 这里我们不禁思考一个问题,如果let在函数作用域中会怎么样,以及var在块作用域中又会怎么样?

3.3.2 块作用域是函数作用域的子集

let在函数作用域外部访问的栗子

function hello() { let x = 3; console.log(x); } hello(); console.log(x);

在这里插入图片描述

从let在函数作用域和之前在块作用域中的访问结果来看,我们会发现结果是相同的。 所以,我们是否能够认为let声明的变量在函数作用域中相当于和块作用域中相同呢? 我认为:应该是基本一致的,都充当局部变量的作用!

var在块作用域外部访问的栗子

if(true) { var x = 3; console.log(x); } console.log(x);

在这里插入图片描述

而从var来看,var声明的变量在函数作用域作为局部变量,但在块中声明的变量却可以不受块的限制,以该块外层的作用域作为变量的作用域,本例中,外层作用域为全局域。

由于函数作用域对于let来说和块作用域差别不大,而块作用域却限制不了var,无法使var成为局部变量。所以,我们说,块作用域是函数作用域的子集。

在这里插入图片描述

3.3.3 ️禁止重复声明

我们之前讲了var可以重复声明,而let与之不同的一点是,在同一个块作用域中,let不允许重复声明。

if(true){ let x = 3; let x = 4; }

在这里插入图片描述

很直观来看,直接就报错了

那如果是var和let的混合重复声明又会怎么样呢?

混合重复声明在块作用域的栗子

if(true){ let x = 3; var x = 4; }

在这里插入图片描述

混合重复声明在函数作用域的栗子

function hello(){ let x = 3; var x = 4; }

在这里插入图片描述 同样都是混用var和let,为什么在函数作用域中的会报错,而块作用域不会呢? 其实,JavaScript引擎会记录遍历声明的标识符和块中的作用域。

当var和let位于一个块中时,我们之前说过var不受块的限制,会位于块外面一层的作用域中,自然不会和let冲突。但如果他们位于同个函数作用域中,var作为局部变量,在函数作用域中,let把函数当成块,也在该作用域中,这时候定义的标识符和作用域相同,自然会产生冲突。

但这时候又有一个疑问了,let和let,var和let同个作用域会报错,但var和var为什么不会呢? 那是因为编辑器会在判断有已经声明的同名变量时忽略var。

3.3.4 暂时性死区​

我们说过var会出现变量提升这个问题,即变量声明会被提前到函数作用域的顶部。

但let与var的重要区别之一就是:let不会出现变量提升的现象。

JavaScript引擎一样会注意到let声明,但在执行该声明之前,不能用任何方式来引用未声明的变量,所以在let声明之前的执行瞬间叫做暂时性死区(temporal dead zone)。

其实也就是let定义某个变量之前,那之前的都属于死区,顾名思义,一旦在死区用这个变量,他就会报错(即声明前先使用了变量)

3.3.5 全局对象

var定义的变量在全局域中会成为window对象(window对象就是全局对象、窗口对象,该对象涉及BOM,可以先不理解)的属性,而let不会。

举个栗子

var x = 1; let y = 2; console.log(window.x) // 1 console.log(window.y) // undefined

在这里插入图片描述

从结果很明显就能看出来,let定义的变量无法做window对象的属性,但var可以

3.3.6 for循环中的let声明

在ES6之前,变量的声明只有var,而var存在变量提升、可重复声明等特点,但在循环的时候还会造成一个问题:迭代变量会泄漏到循环体的外部,因为var不被块作用域限制,所以在块外依然可以访问到块内声明的变量。

而let的出现,这个问题就消失了,举个栗子

for(var i = 0; i } console.log(i); //5 console.log(j); //报错

在这里插入图片描述 打印结果也表面:var在块内定义的循环迭代变量会泄露到循环外,而let不会

3.4 const声明3.4.1 声明并同时初始化

const基本和let一致,但使用时必须初始化!

在这里插入图片描述

从上图可以明显看到,用const声明变量会报错。

正确的使用栗子

const x = "zuolun"; const y = 1024;

在这里插入图片描述 可以看到声明并初始化后不会报错

3.4.2 与let一致的使用

与let的共同点:

作用域:都是块作用域不允许重复声明3.4.3 与let不一致的使用

与let的不同点:

使用时必须初始化一旦初始化后,后续不能修改(这里不是绝对的)不能声明可迭代的循环变量(因为其本身不能变)3.4.4 const声明限制

const的声明限制:只适用于指向它的变量的引用。但如果引用对象的话,修改对象的属性将不受限制,这句话感觉很难理解,我们再具体解释一下。

首先,const保证的不是单纯的值不变,保证的是变量所指向的值不被改变

对于基础数据类型,如:Number、Boolean、String类型来说,变量所指向的值就是初始化的值,所以它们无法被改变。对于对象来说,变量所指向的值是对象的地址,而对象的地址指向了它在堆中所保存的内容,也就是地址的指向不能变,但堆中的内容是可变的,所以我们说修改对象的属性是不受限制的!

举个图的栗子(红色部分​为const不变区,对地址的不变相当于指针指向不变),不懂没关系,后面会再用到它:

在这里插入图片描述

举个代码栗子

const people = { }; //创建一个空对象 people.age = 1024; people.name = "zuolun"; console.log(people);//可以打印 const x = 5; //定义基本数据类型Number x = 7; //报错

在这里插入图片描述 打印结果也表面:const可以修改对象属性,而不能修改基本数据类型!

3.5 最佳的声明风格3.5.1 不用var

由于var会出现变量提升等问题,并且作用域可能会有一定的问题,如块中声明会泄露到外部,而且变量可以重复定义,无限修改,所以安全性也无法得到保证。

所以,为了更明确作用域以及定义不变量(尽可能保证安全性和调试方便),我们尽量不使用var,使用let和const。

3.5.2 const优先,let次之

由于const可以定义不变量(当然并不能完全限制,比如:对象),但像基础数据类型被限制为常量后,如果我们修改他就会报错,这就有助于我们发现一些因意外赋值导致的非预期行为,能更快被修改,而let一般就是用于以后会变化的量。所以我们的使用可以以const优先,let次之。

4. 数据类型4.1 定义

ECMAScript中有6种简单数据类型(原始类型、基本数据类型):Undefined、Null、Boolean、Number、String、Symbol(符号数据类型由es6新增),1种复杂的数据类型(引用数据类型):Object(对象)。

4.2 变量储存方式​

所有的变量都是保存在栈内存中的。

但基本数据类型和引用数据类型有一定的区别:

基本数据类型:值直接保存在栈内存中,值与值之间是独立存在。

引用数据类型:对象是保存到堆内存中的,而变量的值保存了对象的内存地址(对象的引用),保存在栈内存当中。

相当于这个图栗(变量和基本数据类型的值,引用数据类型的地址在栈中,而对象的值在堆中)在这里插入图片描述

4.3 typeof操作符

既然我们有那么多种数据类型,就需要有个东西来鉴别他们,这时候,typeof操作符就出现了。

使用的方式很简单,只需要typeof + 所需要鉴别的东西(可以是变量也可以是具体的值)

举个栗子

const a = 1;//number const b = "1";//string const c = true;//boolean const d = undefined;//underfined const e = { };//object const f = null;//null->object console.log(typeof a); console.log(typeof b); console.log(typeof c); console.log(typeof d); console.log(typeof e); console.log(typeof f);

在这里插入图片描述

我们能够看到基本上所有的类型都能用typeof操作符精准识别,但有一个例外,那就是null。null被鉴定出来是object类型,这是因为typeof操作符认为null这个值是一个空对象的引用。

实际上,函数也被认为是一种对象,而不是一种数据类型。由于函数有自己的特色存在,所以有必要区分出来,举个栗子

function hello(){ //这是一个什么都没定义的空函数 } console.log(typeof hello);//hello为函数名

在这里插入图片描述

所以对一个函数使用typeof的时候,返回结果不是object,而是function。

4.4 字面量和变量

一个基础的概念,字面量是变量的值,变量是声明的名。

栗子

let a = 1;

这里a是变量,1是字面量

4.5 Undefined类型4.5.1 出现的情况

Undefined类型只有一个值就是undefined,分为两种情况:

直接赋值,赋undefined声明变量未初始化

举个栗子

let x = undefined; //undefined赋值 let y; //未初始化 console.log(typeof x); //Undefined类型 console.log(typeof y); //Undefined类型 console.log(x); //undefined字面量 console.log(y); undefined字面量 console.log(x === y); //比较

在这里插入图片描述

从运行结果我们可以很清楚看到用undefined赋值和未初始化这两种情况,typeof结果都是Undefined类型,并且其字面量都是underfined,我们通过比较也会发现这两种值一模一样。

但是,typeof能检查出Undefined的情况不止上面两种,还有未声明的变量也会被认定为是Undefined类型。举个栗子

console.log(typeof z); //Undefined类型 console.log(z); //报错

在这里插入图片描述

这并不矛盾,未声明的变量的类型虽然typeof为Undefined类型,但并没有undefined的字面值。

严格来说,他也不能说是Underfined类型,因为它不存在,但typeof关心的是变量的值,而不是变量是否存在,所以当变量未声明的时候它打印个Underfined表明。

所以,如果我们每次在变量声明的时候都初始化,是不是可以避免underfined字面量的出现,也就是说,如果typeof一个变量结果为Underfined,那么这时候,可以说明该变量未被声明。

4.5.2 布尔属性

underfined字面量是一个假值,也就是放在条件里不会被执行。

let a; //未初始化,类型为Undefined,布尔属性为假 if(a){ //相当于if(false) console.log(1); //不执行 } if(!a){ console.log(2);//可执行 }

在这里插入图片描述

4.6 Null类型4.6.1 出现的情况

Null类型只有一个值就是null,只有一种情况:直接赋值,赋null

举个栗子

let x = null; //null赋值 console.log(x); //字面量为null console.log(typeof x); //Object类型

在这里插入图片描述

这里强调一次:typeof会把null认为是一个空对象,所以返回为Object。

既然null被认定为是一个空对象,所以在定义将来要保存对象值的变量时,可以用null来进行初始化,也就表面当前对象为空。以后如果要判断这个对象是否是空的时候,我们只要看它是否等于null即可。

4.6.2 undefined是null的派生

ECMA-262认为undefined和null表面上相等,举个栗子

console.log(undefined == null); //true console.log(undefined === null); //false

在这里插入图片描述

于是由表面相等便认为:undefined是null的派生(这里我还没有很深刻的理解,以后如果有再补充吧),我们还是需要在操作符那边具体了解 == 和 === 这两个操作符。

4.6.3 布尔属性

null字面量也是一个假值

let a = null; //类型为Null,布尔属性为假 if(a){ //相当于if(false) console.log(1); //不执行 } if(!a){ console.log(2);//可执行 }

在这里插入图片描述

4.7 Boolean类型4.7.1 出现的情况

Boolean有两个字面量,即true和false,true和false都是小写

出现Boolean类型有两种情况:

直接赋值其字面量(true或false)通过Boolean()转型函数转化4.7.2 Boolean()的使用

我们这里探究的主要是Boolean对各种数据类型的转化

Boolean -> Boolean

字面量true为真,字面量false为假

//Boolean -> Boolean console.log(Boolean(true)) //ture console.log(Boolean(false)) //false

String -> Boolean

有内容的字符串为真,空字符串为假,这里重点注意空格串也算有内容,因为空格实际上是有ASCII码的字符,只是看不见而已

// String -> Boolean console.log(Boolean("sdfeae")) //true console.log(Boolean(" ")) //true console.log(Boolean("")) //false

Number -> Boolean

非0的合法数和无穷为真,NaN和0为假(0和非法就是假)

// Number -> Boolean console.log(Boolean(15)) //ture console.log(Boolean(Infinity)) //ture console.log(Boolean(0)) //false console.log(Boolean(NaN)) //false

Undefined -> Boolean

undefined一定假,因为undefined无法进行实际操作

// Undefined -> Boolean console.log(Boolean(undefined)) //false

Null -> Boolean

空也是假

// Null -> Boolean console.log(Boolean(null)) //false

Object -> Boolean

对象无论是空对象,还是有内容的对象,都是真,因为其本身存在

这里注意:空对象{}和空对象指针null是不一样的概念,null可以理解为不存在,而空对象本身存在

// Object -> Boolean console.log(Boolean({ })) //true console.log(Boolean({ 'zuolun':1024})) //true 4.8 Number类型4.8.1 字面量

Number类型的数据默认都以十进制为字面量,即使你写的不是十进制,也会被转化为十进制。十六进制的前缀是0x(x:严格的小写),但十六进制数可以不分大小写。

代码示栗

// 十进制 let x = 10; console.log(x);//10 // 十六进制 -> 十进制 x = 0xff; console.log(x);//255 // 十六进制数大写也不影响 x = 0xFF; console.log(x);//255

在这里插入图片描述

本来的八进制是以0为前缀,但它会在严格模式会出现问题。所以,ES6新增了0o为前缀代表八进制数,建议使用。

// 八进制 -> 十进制 x = 011; console.log(x); x = 0o11; console.log(x);

在这里插入图片描述

这时候我们会发现一个问题,如果我以0为前缀,等于我这时候是八进制表示,但如果我后面的数出现8或者9呢?或者16进制出现>f的数呢?

// 越界的八进制 x = 0o99; // 越界的十六进制 x = 0xFG;

从结果我们可以看见:越界就直接报错,但我们还有一种八进制表示法:也就是以0为前缀,我们看看它会发生什么。

// 越界的八进制 let x = 099; console.log(x);//99

我们发现:以0为前缀的越界的八进制居然可以正常显示。 其实想想也明白,099对十进制来说不就是99吗,所以如果用这种方法会产生歧义:以0为前缀究竟是八进制呢?还是十进制呢?

所以,ES6引入了0o作为前缀。如果使用八进制的话,就一定要以0o为前缀。

4.8.2 浮点数

浮点数实际上就是有小数点的数,比如1.0、1.1、1.01…

存储浮点值的内存空间是储存整数值的两倍,所以为了节省空间,ECMAScript总想法设法把值转化为整数。能够转化的都是小数部分为0的,还有一种是小数点后面没数字的(不推荐该写法)

x = 1.0; console.log(x); //1 x = 1.00; console.log(x); //1 x = 1.000; console.log(x); //1 // 不推荐这种写法 x = 1.; console.log(x); //1

在这里插入图片描述

4.8.3 科学计数法

对于非常大或者非常小的数,我们可以用科学计数法来表示。

表示方法为整数或者浮点数 + e + 以10为底的幂次

代码示栗

let x = 1e4; console.log(x); //10000 x = 1.1e4; console.log(x); //11000 x = 1.1e-4; console.log(x); //0.00011

在这里插入图片描述

4.8.4 浮点的精度问题

经典问题:0.1+0.2是否为0.3?

数学当然是等于了,但是计算机不等于,这里不详细展开。我们只要知道,不要拿浮点数做0.1+0.2 == 0.3 类似此类的判断,因为很可能这个条件是假。

console.log(0.1+0.2); //0.30000000000000004

在这里插入图片描述

4.8.5 + Infinity

由于内存的限制,我们肯定无法无止境的表示数字,也就是说,我们的数存在最大值和最小值,那我们需要思考的不是这些值等于多少,而是当我超过了这些值会怎么样呢?超过最大值:Infinity,小于最小值:-Infinity

举个栗子

//查看最大值,这与浏览器有一定关系,不同浏览器可能不同 console.log(Number.MAX_VALUE); //1.7976931348623157e+308 console.log(Number.MIN_VALUE);//5e-324 //Infinity的出现 console.log(Number.MAX_VALUE+Number.MAX_VALUE);//Infinity console.log(Number.MIN_VALUE-Number.MAX_VALUE*2);//-Infinity

在这里插入图片描述

我们要注意:这个最大值最小值不是简单的加1减1就会越界的,可能是因为舍入的问题还是什么,我具体也不清楚为什么,但初学这也不重要。但我们一定要有这样的概念:超过最大值:Infinity,小于最小值:-Infinity。

4.8.6 NaN

NaN(Not a Number),即不是数值,什么情况会出现它呢?

+0、-0、0互相相除NaN数据参与计算字面量为NaN非法计算:如计算时有字母字符串(除了加法计算)

举个栗子

//+0、-0、0互相相除 console.log(+0/-0); //NaN console.log(+0/0); //NaN console.log(-0/0); //NaN //字面量 console.log(NaN); //NaN //NaN参与计算 console.log(NaN+1); //NaN //非法计算 console.log(1/'A');

在这里插入图片描述

这里要说一个奇怪但又不那么奇怪的现象:NaN !== NaN,个人理解是:可能是由很多种情况造成NaN,所以NaN !== NaN

console.log(NaN === NaN);//false

在这里插入图片描述

其他语言,如python、C语言在0为除数会报错,但JavaScript不会,反而会打印出 + Infinity,感觉有点高数中极限的意思

console.log(1/0);//Infinity console.log(-1/0);//-Infinity

在这里插入图片描述

4.8.7 数值转化Number()

我们这里探究的主要是Number()对各种数据类型的转化

Number -> Number

数值直接转化为十进制,和直接定义数字没区别

//Number -> Number //对十进制数的转化 console.log(Number(11)); //11 //对八进制数的转化 console.log(Number(0o11)); //9 //对十六进制数的转化 console.log(Number(0xff)); //255 //对浮点数的转化 console.log(Number(1.1)); //1.1

String -> Number

Number()忽略字符串中的空白字符和空格,所以空白字符串和空格被当成空处理,空即是假,所以返回0。

而有内容的字符,如果是纯数字或者以0为前缀的可以表示进制的后面加数字或字母,都会被转化为十进制数字,这里注意如果是像为011这种,这里不会被当成八进制,而会被当成十进制。

有内容没办法转化为数字就是NaN,这里包括进制越界。

//对字符串(只有数字)的转化 console.log(Number('11')); //11 console.log(Number('011')); //11 console.log(Number('0o11')); //9 console.log(Number('0xff')); //255 console.log(Number('0xgg')); //进制越界:NaN //对字符串(含有字母)的转化 console.log(Number('aa')); //NaN //对字符串(空)的转化 console.log(Number('')); //0 //对字符串(空格串)的转化 console.log(Number(' ')); //0

Boolean -> Number

false -> 0,true -> 1

// Boolean -> Number //对布尔真值的转化 console.log(Number(true)); //1 //对布尔假值的转化 console.log(Number(false)); //0

Undefined -> Number

undefined是非法,因为undefined无法转化为Number

// Undefined -> Number console.log(Number(undefined)); //NaN

Null -> Number

空也是假,所以返回0

// Null -> Number console.log(Number(null)); //0

Object -> Number

【以后补充】

4.8.8 数值转化parseInt()

由于Number()的使用相对复杂,我们这里介绍ParseInt()。

parseInt()有点像我们的检察官,他只取整数,他忽视空格的存在,只专注于数字。

如果要进行parseInt()为空字符串,检察官也会说这不行,因为取不到整数,所以你是NaN。所以,如果是空串,null,undefined类型转化时就为NaN。

栗子

// undefined、null、"" console.log(parseInt(undefined)); //NAN console.log(parseInt(null)); //NAN console.log(parseInt("")); //NAN

在这里插入图片描述

像underfined、null这种不是字符串的类型,会先转化为字符串再进行判断,也就是"undefined"、"null"再进行判断,这刚好满足下面这点所说。

如果出现进制越界或者出现一个奇怪的符号字母无法构成数字的话,检察官也不再往下查了,直接取之前合法的数字,如果没有合法的数字就直接NaN。

栗子

// 前是合法数字,中途遇到能使进制越界的字母或者数字、小数点 console.log(parseInt('1234abcd')); //1234 console.log(parseInt(' 0xfzf')); //十六进制->15 console.log(parseInt("0o1239")); //八进制没办法转化,所以到o截止 console.log(parseInt('10.224')); //10

在这里插入图片描述

八进制无法转化,那我一定要以八进制的形式解析为十进制的形式该如何?

这里要说的就是parseInt的第二个参数:字符串的存在进制(准确来说应该是字符串的解析形式),也就是表明现在将以我们所设定的进制转化为十进制。由于我已经指明了字符串的存在是什么进制了,所以前缀是可以去掉的。

// 第二参数:以该种形式解析字符串中的数字 console.log(parseInt('1234abcd',10)); //十进制->1234 console.log(parseInt('f',16)); //十六进制->15 console.log(parseInt("11",8)); //八进制->9

在这里插入图片描述

实际使用中,我们一般都会加入第二个参数,否则,parseInt会自己决定如何解析。

4.8.9 数值转化parseFloat()

parseFloat()和parseInt()类似,但这个检察官标准略有不同。

解析方式不同

他解析到字符串末位或者解析到一个无效的浮点数值为止,也就是说第一个小数点有效,第二个小数点无效。

栗子

// 前是合法数字,中途遇到无效浮点数值 console.log(parseFloat('0.1234.254')); //0.1234, 第二个小数点截断 console.log(parseFloat('0.1234a254')); //0.1234 字母截断

在这里插入图片描述

解析方式不同

parseInt可以指定所解析的字符串的存在形式,把它转化为十进制。但parseFloat默认就是以十进制存在形式,无法修改,也就是说像以0x为前缀的十六进制在解析时,只能取到0,x被看做越界(非法),因为十进制不存在x。

栗子

console.log(parseFloat('0xff')); //0, 无法以16进制解析,在x那边截断

在这里插入图片描述

忽略的对象不同

parseInt忽视空格,parseFloat字符串前的空格,就是最前面的一个或多个空格,出现第二次空格会被截断。

栗子

// 空格截断 console.log(parseFloat(' 01.23')); //1.23,第一个空格不被截断 console.log(parseFloat('0 1.23')); //0,第二个空格被截断

在这里插入图片描述

但他们标准也不是完全不同

对空串、null、undefined返回结果一致

因为他们在非字符串上,都会先转化为字符串再进行处理。

栗子

// undefined、null、"" console.log(parseFloat(undefined)); //NAN console.log(parseFloat(null)); //NAN console.log(parseFloat("")); //NAN

在这里插入图片描述

今天就先到这了,未完待续️

如有错误,敬请指正,欢迎交流​,谢谢*(・ω・)ノ



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3