概述
提示:只是总结了一部分,后续有时间会整理出来
JavaScript基础总结目录
- 第1章 编程语言
- 1.1 编程
- 1.2 计算机语言
- 1.3 编程语言
- 1.4 翻译器
- 1.5 编程语言和标记语言区别
- 第2章 计算机基础
- 2.1 计算机组成
- 2.2 数据存储
- 2.3 数据存储单位
- 2.4 程序运行
- 第3章 什么是JavaScript
- 3.1 简短的历史回顾
- 3.2 JavaScript的作用
- 3.3 HTML/CSS/JS 的关系
- 3.4 JS 的组成
- 1. ECMAScript
- 2. DOM(文档对象模型)
- 3. BOM(浏览器对象模型)
- 第4章 HTML中的JavaScript
- 4.1 `<script>`元素
- 1. 标签位置
- 2. 推迟执行脚本
- 3. 异步执行脚本
- 4. 动态加载脚本
- 4.2 行内代码和外部文件
- 1. 行内式
- 2. 内嵌式
- 3. 外部JS文件
- 4.3 JavaScript注释
- 1. 单行注释
- 2. 多行注释
- 4.4 JavaScript输入输出语句
- 第5章 语言基础
- 5.1 语法
- 5.2 关键字和保留字
- 1. 标识符
- 2. 关键字
- 3. 保留字
- 5.3 变量
- 1. 变量的概念
- 2. 变量在内存中的存储
- 3. 变量的使用
- 4. 变量语法扩展
- 5. 变量命名规范
- 5.4 数据类型
- 1. 数据类型简介
- 2. 简单数据类型
- 3. 获取变量数据类型
- 4. 数据类型转换
- 5.5 操作符
- 1. 运算符的分类
- 2. 算数运算符
- 3. 递增和递减运算符
- 4. 比较运算符
- 5. 逻辑运算符
- 6. 赋值运算符
- 7. 运算符优先级
- 5.6 语句
- 1. 流程控制
- 2. if 语句
- 3. switch 语句
- 4. for 循环语句
- 5. while循环语句
- 6. do-while循环
- 7. continue和break语句
- 第6章 基本引用类型
- 6.1 Date
- 1. 使用Date实例化日期对象
- 2. 使用Date实例的方法和属性
- 3. 通过Date实例获取总毫米数
- 4. 格式化日期年月日
- 5. 格式化日期时分秒
- 6. 倒计时效果
- 6.2 RegExp
- 6.3 原始包装类型
- 1. Boolean
- 2. Number
- 3. String
- 6.4 单例内置对象
- 1. Global
- 2. Math
- 第7章 集合引用类型
- 7.1 Object
- 1. 对象的相关概念
- 2. 创建对象的三种方式
- 3. new关键字的作用
- 4. 对象的使用
- 5. 遍历对象
- 7.2 Array
- 1. 数组的概念
- 2. 创建数组
- 3. 数组空位
- 4. 数组索引
- 5. 检测数组(instanceof ,Array.isArray)
- 6. 迭代器方法(keys,values,entries)
- 7. 复制和填充方法( copyWithin,fill)
- 8. 转换方法(valueOf,toString,join)
- 9. 栈方法(push,pop)
- 10. 队列方法(shift,unshift)
- 11. 排序方法(reverse,sort)
- 12. 操作方法(concat,slice)
- 13. 搜索和位置方法(indexOf,lastIndexOf,includes,find,findIndex)
- 14. 迭代方法(every, filter,forEach,map,some)
- 15. 归并方法(reduce,reduceRight)
第1章 编程语言
1.1 编程
编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。
计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以人们要控制计算机一定要通过计算机语言向计算机发出命令。
1.2 计算机语言
-
计算机语言指用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介。
-
计算机语言的种类非常的多,总的来说可以分成机器语言,汇编语言和高级语言三大类。
-
实际上计算机最终所执行的都是 机器语言,它是由“0”和“1”组成的二进制数,二进制是计算机语言的基础。
1.3 编程语言
编程语言:可以通过类似于人类语言的“语言”来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言(Programming Language)。编程语言是用来控制计算机的一系列指令,它有固定的格式和词汇(不同编程语言的格式和词汇不一样),必须遵守。如今通用的编程语言有两种形式:汇编语言和高级语言。
语言类型 | 说明 |
---|---|
汇编语言 | 汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。 |
高级语言 | 高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有C语言、C++、Java、C#、Python、PHP、JavaScript、Go语言、Objective-C、Swift等。 |
1.4 翻译器
高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器。翻译器可以将我们所编写的源代码转换为机器语言,这也被称为二进制化。
1.5 编程语言和标记语言区别
语言 | 说明 |
---|---|
编程语言 | 编程语言有很强的逻辑和行为能力。在编程语言里, 你会看到很多 if else 、for 、while等具有逻辑性和行为能力的指令,这是主动的。 |
标记语言 | 标记语言(html)不用于向计算机发出指令,常用于格式化和链接。标记语言的存在是用来被读取的, 他是被动的。 |
第2章 计算机基础
2.1 计算机组成
2.2 数据存储
- 计算机内部使用二进制 0 和 1来表示数据。
- 所有数据,包括文件、图片等最终都是以二进制数据(0 和 1)的形式存放在硬盘中的。
- 所有程序,包括操作系统,本质都是各种数据,也以二进制数据的形式存放在硬盘中。平时我们所说的安装软件,其实就是把程序文件复制到硬盘中。
- 硬盘、内存都是保存的二进制数据。
2.3 数据存储单位
大小关系:bit < byte < kb < GB < TB < …
- 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
- 字节(Byte):1B = 8b
- 千字节(KB):1KB = 1024B
- 兆字节(MB):1MB = 1024KB
- 吉字节(GB): 1GB = 1024MB
- 太字节(TB): 1TB = 1024GB
2.4 程序运行
计算机运行软件的过程:
- 打开某个程序时,先从硬盘中把程序的代码加载到内存中
- CPU执行内存中的代码
注意:之所以要内存的一个重要原因,是因为 cpu运行太快了,如果只从硬盘中读数据,会浪费cpu性能,所以,才使用存取速度更快的内存来保存运行时的数据。(内存是电,硬盘是机械)
第3章 什么是JavaScript
3.1 简短的历史回顾
- JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思)
- 脚本语言:不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行
- 现在也可以基于 Node.js 技术进行服务器端编程
3.2 JavaScript的作用
- 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
3.3 HTML/CSS/JS 的关系
浏览器执行 JS
浏览器分成两部分:渲染引擎和 JS 引擎
- 浏览器本身并不会执行JS代码,而是通过内置 JavaScript 引擎(解释器) 来执行 JS 代码 。
- JS 引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行。
3.4 JS 的组成
1. ECMAScript
ECMAScript 是由ECMA 国际( 原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为 JavaScript或 JScript,但实际上后两者是 ECMAScript 语言的实现和扩展。
ECMAScript:规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
更多参看MDN: MDN手册
2. DOM(文档对象模型)
文档对象模型(DocumentObject Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。
通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)
3. BOM(浏览器对象模型)
浏览器对象模型(Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。
通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
第4章 HTML中的JavaScript
4.1 <script>
元素
JavaScript 插入 HTML 的主要方法是使用
<script>
元素
<script>
元素有下列 8 个属性。
async
:可选。表示应该立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或等待其他脚本加载。只对外部脚本文件有效。charset
:可选。使用 src 属性指定的代码字符集。这个属性很少使用,因为大多数浏览器不在乎它的值。crossorigin
:可选。配置相关请求的CORS(跨源资源共享)设置。默认不使用CORS。crossorigin= "anonymous"
配置文件请求不必设置凭据标志。crossorigin="use-credentials"
设置凭据标志,意味着出站请求会包含凭据。defer
:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。integrity
:可选。允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI,Subresource Integrity)。如果接收到的资源的签名与这个属性指定的签名不匹配,则页面会报错,脚本不会执行。这个属性可以用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。language
:废弃。最初用于表示代码块中的脚本语言(如"JavaScript"、“JavaScript 1.2"或"VBScript”)。大多数浏览器都会忽略这个属性,不应该再使用它。src
:可选。表示包含要执行的代码的外部文件。type
:可选。代替 language,表示代码块中脚本语言的内容类型(也称 MIME 类型)。按照惯例,这个值始终都是"text/javascript",尽管"text/javascript"和"text/ecmascript"都已经废弃了。JavaScript 文件的 MIME 类型通常是"application/x-javascript",不过给type 属性这个值有可能导致脚本被忽略。在非 IE 的浏览器中有效的其他值还有
"application/javascript"和"application/ecmascript"
。如果这个值是 module,则代码会被当成 ES6 模块,而且只有这时候代码中才能出现 import 和 export 关键字。
1. 标签位置
<script>
元素都被放在页面的<head>
标签内
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script src="example1.js"></script>
<script src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
目的:是把外部的 CSS 和 JavaScript 文件都集中放到一起
问题:把所有 JavaScript文件都放在
<head>
里,也就意味着必须把所有 JavaScript 代码都下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到<body>
的起始标签时开始渲染)。需要很多 JavaScript 的页面,这会导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。
解决:将所有 JavaScript 引用放在
<body>
元素中的页面内容后面
2. 推迟执行脚本
defer
属性:表示脚本在执行的时候不会改变页面的结构。脚本会被延迟到整个页面都解析完毕后再运行。
在
<script>
元素上设置defer 属性
,相当于告诉浏览器立即下载,但延迟执行。
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
注意:对 defer 属性的支持是从 IE4、Firefox 3.5、Safari 5 和 Chrome 7 开始的。其他所有浏览器则会忽略这个属性,按照通常的做法来处理脚本。考虑到这一点,还是把要推迟执行的脚本放在页面底部比较好。
对于 XHTML 文档,指定 defer 属性时应该写成defer="defer"
。
3. 异步执行脚本
async
属性:浏览器立即开始下载,标记为 async 的脚本并不保证能按照它们出现的次序执行
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script async src="example1.js"></script>
<script async src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
注意: 对于 XHTML 文档,指定 async 属性时应该写成 async=“async”。
4. 动态加载脚本
JavaScript 可以使用 DOM API,通过向 DOM 中动态添加 script 元素同样可以加载指定的脚本
let script = document.createElement('script');
script.src = 'gibberish.js';
document.head.appendChild(script);
4.2 行内代码和外部文件
JS 有3种书写位置,分别为行内、内嵌和外部。
1. 行内式
<input type="button" value="点我试试" onclick="alert('Hello World')" />
- 可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick
- 注意单双引号的使用:在HTML中我们推荐使用双引号, JS 中我们推荐使用单引号
- 可读性差, 在html中编写JS大量代码时,不方便阅读;
- 引号易错,引号多层嵌套匹配时,非常容易弄混;
- 特殊情况下使用
2. 内嵌式
<script>
alert('Hello
World~! 内嵌式');
</script>
- 可以将多行JS代码写到 script 标签中
- 内嵌 JS 是学习时常用的方式
3. 外部JS文件
<script src="外部JS文件.js"></script>
- 利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
- 引用外部 JS文件的 script 标签中间不可以写代码
- 适合于JS 代码量比较大的情况
4.3 JavaScript注释
为了提高代码的可读性,JS与CSS一样,也提供了注释功能。
JS中的注释主要有两种,分别是 单行注释 和 多行注释。
1. 单行注释
//
用来注释单行文字( 快捷键 ctrl + /
)
// 我是一行文字,不想被 JS引擎 执行,所以注释起来
2. 多行注释
/* */
用来注释多行文字( 默认快捷键 alt + shift + a
)
快捷键修改为: ctrl + shift + /
vscode → 首选项按钮 → 键盘快捷方式 → 查找 原来的快捷键 → 修改为新的快捷键 → 回车确认
/*
获取用户年龄和姓名
并通过提示框显示出来
*/
4.4 JavaScript输入输出语句
为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
注意:alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。
第5章 语言基础
5.1 语法
5.2 关键字和保留字
1. 标识符
标识(zhi)符:就是指开发人员为变量、属性、函数、参数取的名字。
标识符不能是关键字或保留字。
2. 关键字
关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
3. 保留字
保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。
5.3 变量
1. 变量的概念
白话:变量就是一个装东西的盒子。
通俗:变量是用于存放数据的容器。 我们通过
变量名
获取数据,甚至数据可以修改。
2. 变量在内存中的存储
本质:变量是程序在内存中申请的一块用来存放数据的空间。类似我们酒店的房间,一个房间就可以看做是一个变量。
3. 变量的使用
- 声明变量
//
声明变量
var age; //
声明一个 名称为age 的变量
var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
- 赋值
age = 10; // 给 age
这个变量赋值为 10
=
用来把右边的值赋给左边的变量空间中 此处代表赋值的意思
变量值是程序员保存到变量空间里的值
- 变量的初始化
var age
= 18;
// 声明变量同时赋值为 18
// 声明一个变量并赋值, 我们称之为变量的初始化。
4. 变量语法扩展
- 更新变量
一个变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
var age = 18;
age = 81;
// 最后的结果就是81因为18 被覆盖掉了
- 同时声明多个变量
同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。
var age = 10,
name = 'zs', sex = 2;
- 声明变量特殊情况
情况 | 说明 | 结果 |
---|---|---|
var age ; console.log (age); | 只声明 不赋值 | undefined |
console.log(age) | 不声明 不赋值 直接使用 | 报错 |
age = 10; console.log (age); | 不声明 只赋值 | 10 |
5. 变量命名规范
- 由字母
(A-Za-z)
、数字(0-9)
、下划线(_)
、美元符号( $ )
组成,如:usrAge, num01, _name
- 严格区分大小写。
var app;
和var App;
是两个变量 - 不能以数字开头。 18age 是错误的
- 不能是关键字、保留字。例如:
var、for、while
- 变量名必须有意义。 MMD BBD nl → age
- 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。
myFirstName
推荐翻译网站: 有道 爱词霸
5.4 数据类型
1. 数据类型简介
- 为什么需要数据类型
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。
简单来说,数据类型就是数据的类别型号。比如姓名“张三”,年龄18,这些数据的类型是不一样的。
- 变量的数据类型
变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。
JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定:
var age = 10;
// 这是一个数字型
var areYouOk = '是的';
// 这是一个字符串
在代码运行时,变量的数据类型是由 JS引擎 根据 = 右边变量值的数据类型来判断 的,运行完毕之后, 变量就确定了数据类型。
JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:
var x = 6;
// x 为数字
var x = "Bill";
// x 为字符串
- 数据类型的分类
- 基本数据类型(
Number,String,Boolean,Undefined,Null
) - 复杂数据类型 (
object,Array,function
)
2. 简单数据类型
JavaScript 中的简单数据类型及其说明如下:
1. 数字型 Number
JavaScript 数字类型既可以保存整数,也可以保存小数(浮点数)。
var age = 21;
// 整数
var Age = 21.3747;
// 小数
- 数字型进制
最常见的进制有二进制、八进制、十进制、十六进制。
// 1.八进制数字序列范围:0~7
var num1 = 07;
// 对应十进制的7
var num2 = 019;
// 对应十进制的19
var num3 = 08;
// 对应十进制的8
// 2.十六进制数字序列范围:0~9以及A~F
var num = 0xA;
- 数字型范围
最大值:
Number.MAX_VALUE
,这个值为: 1.7976931348623157e+308
最小值:
Number.MIN_VALUE
,这个值为:5e-32
- 数字型三个特殊值
Infinity
,代表无穷大,大于任何数值
Infinity
,代表无穷小,小于任何数值
NaN
,Not a number,代表一个非数值
- isNaN
用来判断一个变量是否为非数字的类型,返回 true 或者 false
2. 布尔型Boolean
布尔类型有两个值:true 和 false ,其中 true 表示真(对),而 false 表示假(错)。
布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。
console.log(true + 1);
// 2
console.log(false + 1); // 1
3. 字符串型 String
字符串型可以是引号中的任意文本,其语法为 双引号 “” 和 单引号’’
因为 HTML 标签里面的属性使用的是双引号,JS 这里我们更推荐使用单引号。
var strMsg = "我爱JavaScript";
// 使用双引号表示字符串
var strMsg2 = '我爱JavaScript';
// 使用单引号表示字符串
// 常见错误
var strMsg3 = 我爱JavaScript;
// 报错,没使用引号,会被认为是js代码,但js没有这些语法
- 字符串引号嵌套
JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
var strMsg = '我是"高帅富"程序猿';
// 可以用''包含""
var strMsg2 = "我是'高帅富'程序猿";
// 也可以用"" 包含''
//
常见错误
var badQuotes = 'What on earth?"; // 报错,不能 单双引号搭配
- 字符串转义符
类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。
转义符都是 开头的,常用的转义符及其说明如下:
转义符 | 解释说明 |
---|---|
n | 换行符,n 是 newline 的意思 |
斜杠 | |
’ | ’ 单引号 |
" | ”双引号 |
t | tab 缩进 |
b | 空格 ,b 是 blank 的意思 |
- 字符串长度
字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的
length 属性
可以获取整个字符串的长度。
var strMsg = "我是帅气多金的程序猿!";
alert(strMsg.length); // 显示 11
- 字符串拼接
多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
//1.1 字符串 "相加"
alert('hello' + ' ' + 'world'); // hello world
//1.2 数值字符串 "相加"
alert('100' + '100'); // 100100
//1.3 数值字符串 + 数值
alert('11' + 12);
// 1112
总结口诀:数值相加 ,字符相连
- 字符串拼接加强
经常会将字符串和变量来拼接,变量可以很方便地修改里面的值
变量是不能添加引号的,因为加引号的变量会变成字符串
如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写加中间
4. Undefined
一个声明后没有被赋值的变量会有一个默认值undefined ( 如果进行相连或者相加时,注意结果)
var variable;
console.log(variable);
// undefined
console.log('你好' + variable);
// 你好undefined
console.log(11 + variable);
// NaN
console.log(true + variable);
//
NaN
5. Null
一个声明变量给 null 值,里面存的值为空(学习对象时,我们继续研究null)
var vari = null;
console.log('你好' + vari);
// 你好null
console.log(11 + vari);
// 11
console.log(true + vari);
//
1
3. 获取变量数据类型
- 获取检测变量的数据类型
typeof 可用来获取检测变量的数据类型
var num = 18;
console.log(typeof num) // 结果 number
不同类型的返回值
- 字面量
字面量是在源代码中一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值。
- 数字字面量:8, 9, 10
- 字符串字面量:‘黑马程序员’, “大前端”
- 布尔字面量:true,false
4. 数据类型转换
使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。
通俗来说,就是把一种数据类型的变量转换成另一种数据类型,通常会实现3种方式的转换:
- 转换为字符串
- toString() 和 String() 使用方式不一样
- 三种转换方式,更多第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。
- 转换为数字型(重点)
- 注意 parseInt 和 parseFloat 单词的大小写,这2个是重点
- 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
- 转换为布尔型
- 代表空、否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined
- 其余值都会被转换为 true
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true
5.5 操作符
1. 运算符的分类
运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
2. 算数运算符
- 算术运算符概述
概念:算术运算使用的符号,用于执行两个变量或值的算术运算。
console.log(1 + 1); // 2
console.log(1 - 1); // 0
console.log(1 * 1); // 1
console.log(1 / 1); // 1
// 1. % 取余 (取模)
console.log(4 % 2); // 0
console.log(5 % 3); // 2
console.log(3 % 5); // 3
- 浮点数的精度问题
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
// 2. 浮点数 算数运算里面会有问题
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.07 * 100); // 7.000000000000001
所以:不要直接判断两个浮点数是否相等 !
- 表达式和返回值
表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合
简单理解:是由数字、运算符、变量等组成的式子
表达式最终都会有一个结果,返回给开发者,称为返回值
//
是由数字、运算符、变量等组成的式子 我们成为表达式
1 + 1
console.log(1 + 1); // 2 就是返回值
// 1 + 1 = 2
// 在我们程序里面
2 = 1 + 1
把我们的右边表达式计算完毕把返回值给左边
var num = 1 + 1;
3. 递增和递减运算符
- 递增和递减运算符概述
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
在 JavaScript 中,递增(++)和递减( – )既可以放在变量前面,也可以放在变量后面。放在变量前面时,我们可以称为前置递增(递减)运算符,放在变量后面时,我们可以称为后置递增(递减)运算符。
注意:递增和递减运算符必须和变量配合使用。
- 递增运算符
- 前置递增运算符
++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。
使用口诀:先自加,后返回值
// 1. 想要一个变量自己加1
num = num + 1 比较麻烦
var num = 1;
num = num + 1; // ++num
num = num + 1;
console.log(num); // 3
// 2. 前置递增运算符
++ 写在变量的前面
var age = 10; // 11
++age; // 类似于 age = age + 1
console.log(age);
// 3. 先加1
后返回值
var p = 10;
console.log(++p + 10); // 21
- 后置递增运算符
num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。
使用口诀:先返回原值,后自加
var num = 10;
num++; // num = num + 1
++num;
console.log(num); //11
// 1. 前置自增和后置自增如果单独使用 效果是一样的
// 2. 后置自增 口诀:先返回原值 后自加1
var age = 10;
console.log(age++ + 10); // 20
console.log(age); // 11
4. 比较运算符
- 比较运算符概述
概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。
console.log(3 >= 5); // false
console.log(2 <= 4); // true
//1. 我们程序里面的等于符号 是 ==
默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以
console.log(3 == 5); // false
console.log('pink老师' == '刘德华'); // flase
console.log(18 == 18); // true
console.log(18 == '18'); // true
console.log(18 != 18); // false
- 等号比较
// 2. 我们程序里面有全等 一模一样
要求 两侧的值 还有 数据类型完全一致才可以 true
console.log(18 === 18);
console.log(18 === '18'); // false
5. 逻辑运算符
- 逻辑运算符概述
概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断
- 逻辑与&&
两边都是 true才返回 true,否则返回 false
// 1. 逻辑与 &&
and 两侧都为true
结果才是 true
只要有一侧为false
结果就为false
console.log(3 > 5 && 3 > 2); // false
console.log(3 < 5 && 3 > 2); // true
- 逻辑或 ||
两边都是 true才返回 true,否则返回 false
// 2. 逻辑或 || or
两侧都为false
结果才是假 false
只要有一侧为true
结果就是true
console.log(3 > 5 || 3 > 2); // true
console.log(3 > 5 || 3 < 2); // false
- 逻辑非 !
逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false
// 3. 逻辑非
not
!
console.log(!true); // false
- 短路运算(逻辑中断)
短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
- 逻辑与
语法:表达式1 && 表达式2
如果第一个表达式的值为真,则返回表达式2
如果第一个表达式的值为假,则返回表达式1
- 逻辑或
语法:表达式1 || 表达式2
如果第一个表达式的值为真,则返回表达式1
如果第一个表达式的值为假,则返回表达式2
// 1. 用我们的布尔值参与的逻辑运算
true && false
== false
// 2. 123 && 456
是值 或者是 表达式 参与逻辑运算?
// 3. 逻辑与短路运算
如果表达式1 结果为真 则返回表达式2
如果表达式1为假 那么返回表达式1
console.log(123 && 456); // 456
console.log(0 && 456); //
0
console.log(0 && 1 + 2 && 456 * 56789); // 0
console.log('' && 1 + 2 && 456 * 56789); // ''
// 如果有空的或者否定的为假 其余是真的
0
''
null undefined
NaN
// 4. 逻辑或短路运算
如果表达式1 结果为真 则返回的是表达式1 如果表达式1 结果为假 则返回表达式2
console.log(123 || 456); // 123
console.log(123 || 456 || 456 + 123); // 123
console.log(0 || 456 || 456 + 123); // 456
// 逻辑中断很重要 它会影响我们程序运行结果思密达
var num = 0;
console.log(123 || num++);
console.log(num); // 0
6. 赋值运算符
概念:用来把数据赋值给变量的运算符。
var num = 10;
// num = num + 1;
num++
// num = num + 2; // num += 2;
// num += 2;
num += 5;
console.log(num); // 15
var age = 2;
age *= 3;
console.log(age); // 6
7. 运算符优先级
- 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
console.log(4 >= 6 || '人' != '阿凡达' && !(12 * 2 == 144) && true) //true
var num = 10;
console.log(5 == num / 2 && (2 + 2 * num).toString() === '22');//true
console.log('-------------------');
var a = 3 > 5 && 2 < 7 && 3 == 4;
console.log(a);//false
var b = 3 <= 4 || 3 > 1 || 3 != 2;
console.log(b);//true
var c = 2 === "2";
console.log(c);//false
var d = !c || b && a;
console.log(d);//true
5.6 语句
1. 流程控制
在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行顺序来实现我们要完成的功能。
简单理解:流程控制就是来控制代码按照一定结构顺序来执行
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,代表三种代码执行的顺序。
- 顺序结构
顺序结构是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
- 分支结构
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果
JS 语言提供了两种分支结构语句:if 语句、switch 语句
- 循环结构
2. if 语句
1. if 语句
// 语法结构:
// 条件成立执行代码,否则什么也不做
if (条件表达式) {
// 条件成立执行的代码语句
}
语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序由很多个语句组成,一般情况下,会分割成一个一个的语句。
// 1. if 的语法结构
// if (条件表达式) {
//
// 执行语句
// }
// 2. 执行思路
如果 if 里面的条件表达式结果为真 true 则执行大括号里面的 执行语句
// 如果if 条件表达式结果为假 则不执行大括号里面的语句 则执行if 语句后面的代码
// 3. 代码体验
if (3 < 5) {
alert('沙漠骆驼');
}
执行流程:
进入网吧案例:
<script>
// 弹出 prompt 输入框,用户输入年龄, 程序把这个值取过来保存到变量中
// 使用 if 语句来判断年龄,如果年龄大于18 就执行 if 大括号里面的输出语句
var age = prompt('请输入您的年龄:');
if (age >= 18) {
alert('我想带你去网吧偷耳机');
}
</script>
2. if else语句(双分支语句)
// 语法结构:
// 条件成立
执行 if 里面代码,否则执行else 里面的代码
if (条件表达式) {
// [如果] 条件成立执行的代码
} else {
// [否则] 执行的代码
}
// 1. 语法结构
if 如果
else 否则
// 2. 执行思路 如果表达式结果为真 那么执行语句1
否则
执行语句2
// 3. 代码验证
var age = prompt('请输入您的年龄:');
if (age >= 18) {
alert('我想带你去网吧偷耳机');
} else {
alert('滚, 回家做作业去');
}
// 5. if里面的语句1 和 else 里面的语句2 最终只能有一个语句执行
2选1
// 6.
else 后面直接跟大括号
执行流程:
判断闰年案例:
<script>
// 算法:能被4整除且不能整除100的为闰年(如2004年就是闰年,1901年不是闰年)或者能够被 400 整除的就是闰年
// 弹出prompt 输入框,让用户输入年份,把这个值取过来保存到变量中
// 使用 if 语句来判断是否是闰年,如果是闰年,就执行 if 大括号里面的输出语句,否则就执行 else里面的输出语句
// 一定要注意里面的且 &&
还有或者 || 的写法,同时注意判断整除的方法是取余为 0
var year = prompt('请您输入年份:');
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
alert('您输入的年份是闰年');
} else {
alert('您输入的年份是平年');
}
</script>
3. if else if 语句(多分支语句)
// 语法结构:
// 适合于检查多重条件。
if (条件表达式1) {
语句1;
} else if (条件表达式2)
{
语句2;
} else if (条件表达式3)
{
语句3;
....
} else {
// 上述条件都不成立执行此处代码
}
// 1. 多分支语句
就是利用多个条件来选择不同的语句执行 得到不同的结果
多选1 的过程
// 2. if else if语句是多分支语句
// 3. 语法规范
if (条件表达式1) {
// 语句1;
} else if (条件表达式2) {
// 语句2;
} else if (条件表达式3) {
// 语句3;
} else {
// 最后的语句;
}
// 4. 执行思路
// 如果条件表达式1 满足就执行 语句1 执行完毕后,退出整个if 分支语句
// 如果条件表达式1 不满足,则判断条件表达式2
满足的话,执行语句2 以此类推
// 如果上面的所有条件表达式都不成立,则执行else 里面的语句
// 5. 注意点
// (1) 多分支语句还是多选1 最后只能有一个语句执行
// (2) else if 里面的条件理论上是可以任意多个的
// (3) else if 中间有个空格了
执行逻辑:
判断成绩案例:
<script>
// 伪代码按照从大到小判断的思路
// 弹出prompt输入框,让用户输入分数(score),把这个值取过来保存到变量中
// 使用多分支 if else if 语句来分别判断输出不同的值
var score = prompt('请您输入分数:');
if (score >= 90) {
alert('宝贝,你是我的骄傲');
} else if (score >= 80) {
alert('宝贝,你已经很出色了');
} else if (score >= 70) {
alert('你要继续加油喽');
} else if (score >= 60) {
alert('孩子,你很危险');
} else {
alert('熊孩子,我不想和你说话,我只想用鞭子和你说话');
}
</script>
4. 三元表达式
// 语法结构:
表达式1 ? 表达式2 : 表达式3;
// 1. 有三元运算符组成的式子我们称为三元表达式
// 2. ++num
3 + 5
? :
// 3. 语法结构
// 条件表达式 ? 表达式1 : 表达式2
// 4. 执行思路
// 如果条件表达式结果为真 则 返回 表达式1 的值 如果条件表达式结果为假 则返回 表达式2 的值
// 5. 代码体验
// if (num > 5) {
//
result = '是的';
// } else {
//
result = '不是的';
// }
var num = 10;
var result = num > 5 ? '是的' : '不是的'; // 我们知道表达式是有返回值的
console.log(result);
执行思路:
如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值
简单理解: 就类似于 if else (双分支) 的简写
时间补0案例:
<script>
// 用户输入0~59之间的一个数字
// 如果数字小于10,则在这个数字前面补0,(加0 拼接) 否则
不做操作
// 用一个变量接受这个返回值,输出
var time = prompt('请您输入一个 0 ~ 59 之间的一个数字');
// 三元表达式
表达式 ? 表达式1 :表达式2
var result = time < 10 ? '0' + time : time; //
把返回值赋值给一个变量
alert(result);
</script>
3. switch 语句
switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用 switch。
// 语法结构:
switch( 表达式 ){
case value1:
// 表达式 等于 value1 时要执行的代码
break;
case value2:
// 表达式 等于 value2 时要执行的代码
break;
default:
// 表达式 不等于任何一个 value 时要执行的代码
}
// 1. switch 语句也是多分支语句 也可以实现多选1
// 2. 语法结构 switch 转换、开关
case 小例子或者选项的意思
// 3. 执行思路
利用我们的表达式的值 和 case 后面的选项值相匹配 如果匹配上,就执行该case 里面的语句
如果都没有匹配上,那么执行 default里面的语句
// 4. 代码验证
let key = 4
switch (key) {
case 1:
console.log('这是1');
break;
case 2:
console.log('这是2');
break;
case 3:
console.log('这是3');
break;
default:
console.log('没有匹配结果');
}
switch注意事项:
- switch :开关 转换 , case :小例子 选项
- 关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
- 关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号
- switch 表达式的值会与结构中的 case 的值做比较
- 如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码执行结束
- 如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码
注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。
// switch注意事项
var num = 1;
switch (num) {
case 1:
console.log(1);
case 2:
console.log(2);
case 3:
console.log(3);
break;
}
// 1. 我们开发里面 表达式我们经常写成变量
// 2. 我们num 的值 和 case 里面的值相匹配的时候是 全等
必须是值和数据类型一致才可以 num === 1
// 3. break 如果当前的case里面没有break 则不会退出switch 是继续执行下一个case
switch 语句和 if else if 语句的区别:
- 一般情况下,它们两个语句可以相互替换
- switch…case 语句通常处理 case为比较确定值的情况, 而 if…else…语句更加灵活,常用于范围判断(大于、等于某个范围)
- switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if…else 语句有几种条件,就得判断多少次。
- 当分支比较少时,if… else语句的执行效率比 switch语句高。
- 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。
查询水果案例:
<script>
// 弹出 prompt 输入框,让用户输入水果名称,把这个值取过来保存到变量中。
// 将这个变量作为 switch 括号里面的表达式。
// case 后面的值写几个不同的水果名称,注意一定要加引号 ,因为必须是全等匹配。
// 弹出不同价格即可。同样注意每个 case 之后加上 break ,以便退出 switch 语句。
// 将 default 设置为没有此水果。
var fruit = prompt('请您输入查询的水果:');
switch (fruit) {
case '苹果':
alert('苹果的价格是 3.5/斤');
break;
case '榴莲':
alert('榴莲的价格是 35/斤');
break;
default:
alert('没有此水果');
}
</script>
4. for 循环语句
1. for 循环
目的:重复执行某些代码
console.log('媳妇我错了');
console.log('媳妇我错了');
console.log('媳妇我错了');
console.log('---------------------');
for (var i = 1; i < 1000; i++) {
console.log('媳妇我错了');
}
// 语法结构:
for(初始化变量; 条件表达式; 操作表达式 ){
//循环体
}
名称 | 作用 |
---|---|
初始化变量 | 通常被用于初始化一个计数器,该表达式可以使用 var 关键字声明新的变量,这个变量帮我们来记录次数。 |
条件表达式 | 用于确定每一次循环是否能被执行。如果结果是 true 就继续循环,否则退出循环。 |
操作表达式 | 用于确定每一次循环是否能被执行。如果结果是 true 就继续循环,否则退出循环。 |
// 1. for 重复执行某些代码, 通常跟计数有关系
// 2. for 语法结构
// for (初始化变量; 条件表达式; 操作表达式) {
//
// 循环体
// }
// 3. 初始化变量 就是用var 声明的一个普通变量, 通常用于作为计数器使用
// 4. 条件表达式 就是用来决定每一次循环是否继续执行 就是终止的条件
// 5. 操作表达式 是每次循环最后执行的代码 经常用于我们计数器变量进行更新(递增或者递减)
// 6. 代码体验 我们重复打印100局 你好
for (var i = 1; i <= 100; i++) {
console.log('你好吗');
}
执行过程:
初始化变量,初始化操作在整个 for 循环只会执行一次。
条件表达式,如果为true,则执行循环体语句,否则退出循环,循环结束。
- 执行操作表达式,此时第一轮结束。
- 第二轮开始,直接去执行条件表达式(不再初始化变量),如果为 true ,则去执行循环体语句,否则退出循环。
- 继续执行操作表达式,第二轮结束。
- 后续跟第二轮一致,直至条件表达式为假,结束整个 for 循环。
// for 循环的执行过程
for (var i = 1; i <= 100; i++) {
console.log('你好吗');
}
// 1. 首先执行里面的计数器变量
var i = 1 .但是这句话在for 里面只执行一次
index
// 2. 用 i <= 100 来判断是否满足条件, 如果满足条件
就去执行 循环体
不满足条件退出循环
// 3. 最后去执行 i++
i++是单独写的代码 递增
第一轮结束
// 4. 接着去执行 i <= 100 如果满足条件
就去执行 循环体
不满足条件退出循环
for循环重复相同代码:
<script>
// for 循环可以执行相同的代码
for (var i = 1; i <= 10; i++) {
console.log('媳妇我错了');
}
// 我们可以让用户控制输出的次数
var num = prompt('请您输入次数');
for (var i = 1; i <= num; i++) {
console.log('媳妇我错了');
}
</script>
for循环重复不同的代码:
<script>
// for 循环可以重复执行不同的代码
因为我们有计数器变量 i 的存在 i每次循环值都会变化
// 我们想要输出1个人 1~100岁
// for (var i = 1; i <= 100; i++) {
//
console.log('这个人今年' + i + '岁了');
// }
for (var i = 1; i <= 100; i++) {
if (i == 1) {
console.log('这个人今年1岁了,他出生了');
} else if (i == 100) {
console.log('这个人今年100岁了,他死了');
} else {
console.log('这个人今年' + i + '岁了');
}
}
</script>
for循环重复某些操作:
<script>
// for 循环重复执行某些操作 比如说我们做了100次加法运算
// 求 1~100 之间的整数累加和
//
需要循环100次,我们需要一个计数器
i
// 我们需要一个存储结果的变量 sum ,但是初始值一定是 0
// 核心算法:1 + 2 + 3 + 4 ....
,sum
=
sum + i;
var sum = 0; // 求和 的变量
for (var i = 1; i <= 100; i++) {
// sum = sum + i;
sum += i;
}
console.log(sum);// 5050
</script>
for循环案例:
- 求1-100之间所有数的平均值 需要一个 sum 和的变量 还需要一个平均值 average 变量
var sum = 0;
var average = 0;
for (var i = 1; i <= 100; i++) {
sum = sum + i;
}
average = sum / 100;
console.log(average);
- 求1-100之间所有偶数和奇数的和 我们需要一个偶数的和变量 even 还需要一个奇数 odd
var even = 0;
var odd = 0;
for (var i = 1; i <= 100; i++) {
if (i % 2 == 0) {
even = even + i;
} else {
odd = odd + i;
}
}
console.log('1~100 之间所有的偶数和是' + even);
console.log('1~100 之间所有的奇数和是' + odd);
- 求1-100之间所有能被3整除的数字的和
var result = 0;
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0) {
// result = result + i;
result += i;
}
}
console.log('1~100之间能够被3整数的数字的和是:' + result);
- 求学生成绩案例
<script>
// 弹出输入框输入总的班级人数(num)
// 依次输入学生的成绩( 保存起来 score), 此时我们需要用到
// for 循环, 弹出的次数跟班级总人数有关系 条件表达式 i <= num
// 进行业务处理: 计算成绩。 先求总成绩( sum), 之后求平均成绩( average)
// 弹出结果
var num = prompt('请输入班级的总人数:'); // num 总的班级人数
var sum = 0; // 求和的变量
var average = 0; // 求平均值的变量
for (var i = 1; i <= num; i++) {
var score = prompt('请您输入第' + i + '个学生成绩');
// 因为从prompt取过来的数据是 字符串型的需要转换为数字型
sum = sum + parseFloat(score);
}
average = sum / num;
alert('班级总的成绩是' + sum);
alert('班级平均分是:' + average);
</script>
- 一行打印n个星星
<script>
// 一行打印五个星星
// console.log('★★★★★');
// for (var i = 1; i <= 5; i++) {
//
console.log('★');
// }
// var str = '';
// for (var i = 1; i <= 5; i++) {
//
str = str + '★';
// }
// console.log(str);
var num = prompt('请输入星星的个数');
var str = '';
for (var i = 1; i <= num; i++) {
str = str + '★'
}
document.write(str)
</script>
断点调试:
断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。断点调试可以帮助观察程序的运行过程
断点调试的流程:
7. 浏览器中按 F12--> sources -->找到需要调试的文件-->在程序的某一行设置断点
8. Watch: 监视,通过watch
可以监视变量的值的变化,非常的常用。
9. 摁下F11
,程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。
2. 双重for循环
循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环语句中,可以再嵌套一个for 循环,这样的 for 循环语句我们称之为双重for循环。
// 语法结构:
for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
for (内循环的初始; 内循环的条件; 内循环的操作表达式) {
需执行的代码;
}
}
<script>
// 1. 双重for循环 语法结构
// for (外层的初始化变量; 外层的条件表达式; 外层的操作表达式) {
//
for (里层的初始化变量; 里层的条件表达式; 里层的操作表达式) {
//
// 执行语句;
//
}
// }
// 2. 我们可以把里面的循环看做是外层循环的语句
// 3. 外层循环循环一次, 里面的循环执行全部
// 4. 代码验证
for (var i = 1; i <= 3; i++) {
console.log('这是外层循环第' + i + '次');
for (var j = 1; j <= 3; j++) {
console.log('这是里层的循环第' + j + '次');
}
}
</script>
- 内层循环可以看做外层循环的循环体语句
- 内层循环执行的顺序也要遵循 for 循环的执行顺序
- 外层循环执行一次,内层循环要执行全部次数
- 打印五行五列星星:
// 打印五行五列星星
var str = '';
for (var i = 1; i <= 5; i++) { // 外层循环负责打印五行
for (var j = 1; j <= 5; j++) { // 里层循环负责一行打印五个星星
str = str + '★';
}
// 如果一行打印完毕5个星星就要另起一行 加 n
str = str + '<br>';
}
document.write(str)
- 打印n行n列的星星
<script>
// 打印n行n列的星星
var rows = prompt('请您输入行数:');
var cols = prompt('请您输入列数:');
var str = '';
for (var i = 1; i <= rows; i++) {
for (var j = 1; j <= cols; j++) {
str = str + '★';
}
str += '<br>';
}
document.write(str)
</script>
- 打印倒三角形
<script>
// 打印倒三角形案例
var str = '';
for (var i = 1; i <= 10; i++) { // 外层循环控制行数
for (var j = i; j <= 10; j++) { // 里层循环打印的个数不一样
j = i
str = str + '★';
}
str += '<br>';
}
document.write(str)
</script>
- 九九乘法表案例
<script>
// 九九乘法表
// 一共有9行,但是每行的个数不一样,因此需要用到双重 for 循环
// 外层的 for 循环控制行数 i ,循环9次 ,可以打印 9 行
// 内层的 for 循环控制每行公式
j
// 核心算法:每一行 公式的个数正好和行数一致, j <= i;
// 每行打印完毕,都需要重新换一行
var str = '';
for (var i = 1; i <= 9; i++) { // 外层循环控制行数
for (var j = 1; j <= i; j++) { // 里层循环控制每一行的个数
j <= i
// 1 × 2 = 2
// str = str + '★';
str += j + '×' + i + '=' + i * j + 't';
}
str += '<br>';
}
document.write(str)
</script>
5. while循环语句
// 语法结构:
while (条件表达式) {
// 循环体代码
}
执行思路:
- 先执行条件表达式,如果结果为 true,则执行循环体代码;如果为 false,则退出循环,执行后面代码
- 执行循环体代码
- 循环体代码执行完毕后,程序会继续判断执行条件表达式,如条件仍为true,则会继续执行循环体,直到循环条件为 false 时,整个循环过程才会结束
注意:使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环
// 1. while 循环语法结构
while 当...的时候
// while (条件表达式) {
//
// 循环体
// }
// 2. 执行思路
当条件表达式结果为true 则执行循环体 否则 退出循环
// 3. 代码验证
var num = 1;
while (num <= 100) {
console.log('好啊有');
num++;
}
// 4. 里面应该也有计数器 初始化变量
// 5. 里面应该也有操作表达式
完成计数器的更新 防止死循环
while循环案例:
- 打印人的一生,从1岁到100岁
var i = 1;
while (i <= 100) {
console.log('这个人今年' + i + '岁了');
i++;
}
- 计算 1 ~ 100 之间所有整数的和
var sum = 0;
var j = 1;
while (j <= 100) {
sum += j;
j++
}
console.log(sum);
- 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
<script>
// while循环案例
// 1. 打印人的一生,从1岁到100岁
var i = 1;
while (i <= 100) {
console.log('这个人今年' + i + '岁了');
i++;
}
// 2. 计算 1 ~ 100 之间所有整数的和
var sum = 0;
var j = 1;
while (j <= 100) {
sum += j;
j++
}
console.log(sum);
// 3. 弹出一个提示框, 你爱我吗?
如果输入我爱你,就提示结束,否则,一直询问。
var message = prompt('你爱我吗?');
while (message !== '我爱你') {
message = prompt('你爱我吗?');
}
alert('我也爱你啊!');
</script>
6. do-while循环
// 语法结构:
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
执行思路:
- 先执行一次循环体代码
- 再执行条件表达式,如果结果为 true,则继续执行循环体代码,如果为 false,则退出循环,继续执行后面代码
注意:先再执行循环体,再判断,do…while循环语句至少会执行一次循环体代码
<script>
// 1.do while 循环 语法结构
do {
// 循环体
} while (条件表达式)
// 2.
执行思路 跟while不同的地方在于 do while 先执行一次循环体 在判断条件 如果条件表达式结果为真,则继续执行循环体,否则退出循环
// 3. 代码验证
var i = 1;
do {
console.log('how are you?');
i++;
} while (i <= 100)
// 4. 我们的do while 循环体至少执行一次
</script>
do while循环案例:
- 打印人的一生,从1岁到100岁
var i = 1;
do {
console.log('这个人今年' + i + '岁了');
i++;
} while (i <= 100)
- 计算 1 ~ 100 之间所有整数的和
var sum = 0;
var j = 1;
do {
sum += j;
j++;
} while (j <= 100)
console.log(sum);
- 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
do {
var message = prompt('你爱我吗?');
} while (message !== '我爱你')
alert('我也爱你啊');
7. continue和break语句
continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。
例如,吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子,其代码实现如下:
for (var i = 1; i <= 5; i++) {
if (i == 3) {
console.log('这个包子有虫子,扔掉');
continue; // 跳出本次循环,跳出的是第3次循环
}
console.log('我正在吃第' + i + '个包子呢');
}
break 关键字用于立即跳出整个循环(循环结束)。
例如,吃5个包子,吃到第3个发现里面有半个虫子,其余的不吃了,其代码实现如下:
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整个for 循环,跳到整个for下面的语句
}
console.log('我正在吃第' + i + '个包子呢');
}
第6章 基本引用类型
6.1 Date
Date 对象和 Math 对象不一样,Date是一个构造函数,所以使用时需要实例化后才能使用其中具体方法和属性。Date 实例用来处理日期和时间
1. 使用Date实例化日期对象
- 获取当前时间必须实例化
// 1. 使用Date
如果没有参数 返回当前系统的当前时间
var date = new Date();
document.write(date)
// 2. 参数常用的写法
数字型
2019, 10, 01
或者是 字符串型 '2019-10-1 8:8:8'
var date1 = new Date(2019, 10, 1);
console.log(date1); // 返回的是 11月 不是 10月
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2);
- 获取指定时间的日期对象
var future = new Date('2019/5/1');
注意:如果创建实例时并未传入参数,则得到的日期对象是当前时间对应的日期对象
2. 使用Date实例的方法和属性
3. 通过Date实例获取总毫米数
总毫秒数的含义:基于1970年1月1日(世界标准时间)起的毫秒数
获取总毫秒数
// 获得Date总的毫秒数(时间戳)
不是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数
// 1. 通过 valueOf()
getTime()
var date = new Date();
console.log(date.valueOf()); // 就是 我们现在时间 距离1970.1.1 总的毫秒数
console.log(date.getTime());
// 2. 简单的写法 (最常用的写法)
var date1 = +new Date(); // +new Date()
返回的就是总的毫秒数
console.log(date1);
// 3. H5 新增的 获得总的毫秒数
console.log(Date.now());
4. 格式化日期年月日
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear()); // 返回当前日期的年
2019
console.log(date.getMonth() + 1); // 月份 返回的月份小1个月
记得月份+1 呦
console.log(date.getDate()); // 返回的是 几号
console.log(date.getDay()); // 3
周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
// 我们写一个 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
5. 格式化日期时分秒
// 格式化日期 时分秒
var date = new Date();
console.log(date.getHours()); // 时
console.log(date.getMinutes()); // 分
console.log(date.getSeconds()); // 秒
// 要求封装一个函数返回当前的时分秒 格式 08:08:08
function getTimer() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
console.log(getTimer());
6. 倒计时效果
html部分
<div>
<span class="hour">1</span> <strong>:</strong>
<span class="minute">2</span> <strong>:</strong>
<span class="second">3</span>
</div>
css部分
<style>
span {
/* 转化span模式,使span能设置宽高 */
display: inline-block;
width: 40px;
height: 40px;
background-color: #333;
color: #fff;
font-weight: 900;
/* 使方块中文字居中 */
text-align: center;
line-height: 40px;
}
</style>
js部分
<script>
//获取元素
var hour = document.querySelector(".hour");
var minute = document.querySelector(".minute");
var second = document.querySelector(".second");
//获取截止时间的时间戳(单位毫秒)
var inputTime = +new Date("2021-12-27 09:00:00");
//我们先调用countDown函数,可以避免在打开界面后停一秒后才开始倒计时
countDown();
//定时器 每隔一秒变化一次
setInterval(countDown, 1000);
function countDown() {
//获取当前时间的时间戳(单位毫秒)
var nowTime = +new Date();
//把剩余时间毫秒数转化为秒
var times = (inputTime - nowTime) / 1000;
//计算小时数 转化为整数
var h = parseInt(times / 60 / 60 % 24);
//如果小时数小于 10,要变成 0 + 数字的形式 赋值给盒子
hour.innerHTML = h < 10 ? "0" + h : h;
//计算分钟数 转化为整数
var m = parseInt(times / 60 % 60);
//如果分钟数小于 10,要变成 0 + 数字的形式 赋值给盒子
minute.innerHTML = m < 10 ? "0" + m : m;
//计算描述 转化为整数
var s = parseInt(times % 60);
//如果秒钟数小于 10,要变成 0 + 数字的形式 赋值给盒子
second.innerHTML = s < 10 ? "0" + s : s;
}
</script>
6.2 RegExp
6.3 原始包装类型
1. Boolean
2. Number
3. String
6.4 单例内置对象
对内置对象的定义是“任何由 ECMAScript 实现提供、与宿主环境无关,并在 ECMAScript
程序开始执行时就存在的对象”。
1. Global
Global对象为一种兜底对象,它所针对的是不属于任何对象的属性和方法。
1. URL 编码方法
encodeURI()
和encodeURIComponent()
方法用于编码统一资源标识符(URI),以便传给浏览器。
ecnodeURI()
方法用于对整个 URI 进行编码
let url = "http://www.wrox.com/illegal value.js#start";
console.log(encodeURI(url));//http://www.wrox.com/illegal%20value.js#start
encodeURIComponent()
方法用于编码 URI 中单独的组件
let url = "http://www.wrox.com/illegal value.js#start";
console.log(encodeURIComponent(url));//http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.js%23start
区别:
encodeURI()不会编码属于 URL 组件的特殊字符,比如冒号、斜杠、问号、井号
encodeURIComponent()会编码它发现的所有非标准字符
2. eval()方法
eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。
console.log(eval('2 + 2'));
// expected output: 4
console.log(eval(new String('2 + 2')));
// expected output: 2 + 2
console.log(eval('2 + 2') === eval('4'));
// expected output: true
console.log(eval('2 + 2') === eval(new String('2 + 2')));
// expected output: false
3. Global 对象属性
4. window 对象
浏览器将 window 对象实现为 Global对象的代理。因此,所有全局作用域中声明的变量和函数都变成了 window 的属性。
var color = "red";
function sayColor () {
console.log(window.color);
}
window.sayColor(); // "red"
2. Math
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
// Math数学对象 不是一个构造函数 ,所以我们不需要new 来调用 而是直接使用里面的属性和方法即可
console.log(Math.PI); // 一个属性 圆周率
console.log(Math.max(1, 99, 3)); // 99
console.log(Math.max(-1, -10)); // -1
console.log(Math.max(1, 99, '张三疯')); // NaN
console.log(Math.max()); // -Infinity
注意:上面的方法使用时必须带括号
获取指定范围内的随机整数:
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
第7章 集合引用类型
7.1 Object
1. 对象的相关概念
什么是对象?
在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的。
属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)
为什么需要对象?
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。
例如,将“张三疯”的个人的信息保存在数组中的方式为:
var arr = [‘张三疯’, ‘男', 128,154];
上述例子中用数组保存数据的缺点是:数据只能通过索引值访问,开发者需要清晰的清除所有的数据的排行才能准确地获取数据,而当数据量庞大时,不可能做到记忆所有数据的索引值。
为了让更好地存储一组数据,对象应运而生:对象中为每项数据设置了属性名称,可以访问数据更语义化,数据结构清晰,表意明显,方便开发者使用。
使用对象记录上组数据为:
var obj = {
"name":"张三疯",
"sex":"男",
"age":128,
"height":154
}
JS中的对象表达结构更清晰,更强大。
2. 创建对象的三种方式
使用对象字面量创建对象
就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法;
{ } 里面采取键值对的形式表示
键:相当于属性名
值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
var star = {
name : '张三疯',
age : 18,
sex : '男',
sayHi : function(){
alert('雷猴啊~');
}
};
利用 new Object 创建对象
创建空对象
var obj = new Object()
给空对象添加属性和方法
// 利用 new Object 创建对象
var obj = new Object(); // 创建了一个空的对象
obj.uname = '张三疯';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('hi~');
}
// (1) 我们是利用 等号 = 赋值的方法 添加对象的属性和方法
// (2) 每个属性和方法之间用 分号结束
console.log(obj.uname);
console.log(obj['sex']);
obj.sayHi();
注意:
Object() :第一个字母大写
new Object() :需要 new 关键字
使用的格式:对象.属性 = 值;
利用构造函数创建对象
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
// 构造函数和对象
// 1. 构造函数
明星 泛指的某一大类
它类似于 java 语言里面的
类(class)
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
// 2. 对象 特指 是一个具体的事物 刘德华 ==
{name: "刘德华", age: 18, sex: "男", sing: ƒ}
var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
console.log(ldh);
// 3. 我们利用构造函数创建对象的过程我们也称为对象的实例化
注意事项:
- 构造函数约定首字母大写。
- 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
- 构造函数中不需要 return 返回结果。
- 当我们创建对象的时候,必须用 new 来调用构造函数。
- 构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
- 创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化
3. new关键字的作用
- 在构造函数代码开始执行之前,创建一个空对象;
- 修改this的指向,把this指向创建出来的空对象;
- 执行函数的代码
- 在函数完成之后,返回this—即创建出来的对象
// new关键字执行过程
// 1. new 构造函数可以在内存中创建了一个空的对象
// 2. this 就会指向刚才创建的空对象
// 3. 执行构造函数里面的代码 给这个空对象添加属性和方法
// 4. 返回这个对象
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', 18, '男');
4. 对象的使用
对象的属性
对象中存储具体数据的 "键值对"中的 "键"称为对象的属性,即对象中存储具体数据的项
对象的方法
对象中存储函数的 "键值对"中的 "键"称为对象的方法,即对象中存储函数的项
访问对象的属性
对象里面的属性调用 :
对象.属性名
,这个小点 . 就理解为“ 的 ”
对象里面属性的另一种调用方式 :对象[‘属性名’]
,注意方括号里面的属性必须加引号
let obj = new Object()
obj.name = '张三疯'
obj.age = 18
console.log(obj.name)// 张三疯
console.log(obj['age'])// 18
调用对象的方法
对象里面的方法调用:
对象.方法名()
,注意这个方法名字后面一定加括号
let obj = new Object()
obj.name = '张三疯'
obj.age = 18
obj.hobby = () => {
return "我喜欢编程"
}
console.log(obj.name)// 张三疯
console.log(obj['age'])// 18
console.log(obj.hobby());// 我喜欢编程
变量、属性、函数、方法总结
属性是对象的一部分,而变量不是对象的一部分,变量是单独存储数据的容器
变量:单独声明赋值,单独存在
属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
函数:单独存在的,通过“函数名()”的方式就可以调用
方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。
5. 遍历对象
for...in
语句用于对数组或者对象的属性进行循环操作。
for (变量 in 对象名字) {
// 在此执行代码
}
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
// 遍历对象
let obj = {
name: '张三疯',
age: 18,
sex: '男',
fn: function () {
return '张三疯,性别:男,今年18岁'
}
}
for (let key in obj) {
console.log(key); // k 变量 输出
得到的是 属性名
console.log(obj[key]); // obj[k] 得到是 属性值
console.log(key + ':' + obj[key])
}
// 我们使用 for in 里面的变量 我们喜欢写 k
或者
key
7.2 Array
1. 数组的概念
数组可以把一组相关的数据一起存放,并提供方便的访问(获取)方式。
数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
2. 创建数组
1. 利用 new 创建数组
let 数组名 = new Array() ;
let arr = new Array();
// 创建一个新的空数组
如果知道数组中元素的数量,那么可以给构造函数传入一个数值,然后
length 属性
就会被自动创建并设置为这个值
let arr1 = new Array(20);// 给构造函数传入一个数值
console.log(arr1); // (20) [空属性 × 20]
给 Array 构造函数传入要保存的元素
let colors = new Array("red", "blue", "green");
console.log(colors) // ['red', 'blue', 'green']
创建数组时可以给构造函数传一个值。这时候就有点问题了,因为如果这个值是数值,则会创建一个长度为指定数值的数组;而如果这个值是其他类型的,则会创建一个只包含该特定值的数组。
let arr2 = new Array(3); // 创建一个包含 3 个元素的数组
let names = new Array("Greg"); // 创建一个只包含一个元素,即字符串"Greg"的数组
console.log(arr2) //(3) [空属性 × 3]
console.log(names) //['Greg']
使用 Array 构造函数时,也可以省略 new 操作符。
let 数组名 = Array() ;
let arr = Array();
// 创建一个新的空数组
let arr2 = Array(3); // 创建一个包含 3 个元素的数组
let names = Array("Greg"); // 创建一个只包含一个元素,即字符串"Greg"的数组
console.log(arr2) //(3) [空属性 × 3]
console.log(names) //['Greg']
2. 利用数组字面量创建数组
数组字面量是在中括号中包含以逗号分隔的元素列表
//1. 使用数组字面量方式创建空的数组
var
数组名 = [];
//2. 使用数组字面量方式创建带初始值的数组
var
数组名 = ['小白','小黑','大黄','瑞奇'];
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个元素的数组
let arr = []; // 创建一个空数组
let values = [1,2,]; // 创建一个包含 2 个元素的数组
注意: 与对象一样,在使用数组字面量表示法创建数组不会调用 Array 构造函数。
3. ES6 新增的用于创建数组的静态方法:from()和 of()
from()用于将类数组结构转换为数组实例
Array.from()
的第一个参数是一个类数组对象
,即任何可迭代的结构,或者有一个 length 属性和可索引元素的结构。
字符串会被拆分为单字符数组:
// 字符串会被拆分为单字符数组
console.log(Array.from("Matt")); // ["M", "a", "t", "t"]
使用 from()将集合和映射转换为一个新数组:
const m = new Map().set(1, 2)
.set(3, 4);
const s = new Set().add(1)
.add(2)
.add(3)
.add(4);
console.log(Array.from(m)); // [[1, 2], [3, 4]]
console.log(Array.from(s)); // [1, 2, 3, 4]
Array.from()对现有数组执行浅复制:
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1);
console.log(a1); // [1, 2, 3, 4]
alert(a1 === a2); // false
使用任何可迭代对象:
// 可以使用任何可迭代对象
const iter = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
yield 4;
}
};
console.log(Array.from(iter)); // [1, 2, 3, 4]
Symbol.iterator 为每一个对象定义了默认的迭代器。当需要对一个对象进行迭代时(比如开始用于一个for…of循环中),它的@@iterator方法都会在不传参情况下被调用,返回的迭代器用于获取要迭代的值。
arguments
对象可以被轻松地转换为数组:
function getArgsArray() {
return Array.from(arguments);
}
console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3, 4]
from()也能转换带有必要属性的自定义对象:
const arrayLikeObject = {
0: 1,
1: 2,
2: 3,
3: 4,
length: 4
};
console.log(arrayLikeObject);// {0: 1, 1: 2, 2: 3, 3: 4, length: 4}
console.log(Array.from(arrayLikeObject)); // [1, 2, 3, 4]
Array.from()的第二个可选的映射函数参数
,这个函数可以直接增强新数组的值,而无须像调用 Array.from().map()那样先创建一个中间数组。
Array.from()的第三个可选参数
,用于指定映射函数中 this 的值。但这个重写的 this 值在箭头函数中不适用。
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1, x => x ** 2);
const a3 = Array.from(a1, function (x) { return x ** this.exponent }, { exponent: 2 });
console.log(a2); // [1, 4, 9, 16]
console.log(a3); // [1, 4, 9, 16]
Array.of()可以把一组参数转换为数组。
console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
console.log(Array.of(undefined)); // [undefined]
3. 数组空位
使用数组字面量初始化数组时,可以使用一串逗号来创建空位(hole)。
const options = [, , , , ,]; // 创建包含 5 个元素的数组
console.log(options.length); // 5
console.log(options); // [空属性 × 5]
ES6 新增方法普遍将这些空位当成存在的元素,只不过值为 undefined
:
const options = [1, , , , 5];
for (const option of options) {
console.log(option === undefined);
}
// false
// true
// true
// true
// false
使用 ES6 的 Array.from()创建的包含 3 个空位的数组
const a = Array.from([, , ,]); // 使用 ES6 的 Array.from()创建的包含 3 个空位的数组
for (const val of a) {
alert(val === undefined);
}
// true
// true
// true
alert(Array.of(...[, , ,])); // [undefined, undefined, undefined]
for (const [index, value] of options.entries()) {
alert(value);
}
// 1
// undefined
// undefined
// undefined
// 5
注意 由于行为不一致和存在性能隐患,因此实践中要避免使用数组空位。如果确实需要空位,则可以显式地用 undefined 值代替。
4. 数组索引
索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)
数组可以通过索引来访问、设置、修改对应的数组元素,可以通过“数组名[索引]”的形式来获取数组中的元素。
let colors = ["red", "blue", "green"]; // 定义一个字符串数组
console.log(colors[0]); // 显示第一项
colors[2] = "black"; // 修改第三项
colors[3] = "brown"; // 添加第四项
console.log(colors)//['red', 'blue', 'black', 'brown']
通过修改 length 属性,可以从数组末尾删除或添加元素
- 从数组末尾删除
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
colors.length = 2;
console.log(colors) // ['red', 'blue']
console.log(colors[2]); // undefined
//将数组 colors 的 length 设置为 4,虽然数组只包含 3 个元素。
//位置 3 在数组中不存在,因此访问其值会返回特殊值 undefined。
- 从数组末尾添加元素
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
colors[colors.length] = "black"; // 添加一种颜色(位置 3)
colors[colors.length] = "brown"; // 再添加一种颜色(位置 4)
console.log(colors)//(5) ['red', 'blue', 'green', 'black', 'brown']
注意: 数组最多可以包含
4 294 967 295
个元素,这对于大多数编程任务应该足够了。如果尝试添加更多项,则会导致抛出错误。以这个最大值作为初始值创建数组,可能导致脚本运行时间过长的错误。
5. 检测数组(instanceof ,Array.isArray)
问题:判断一个对象是不是数组
- instanceof ()方法
判断某个实例(arr)是否属于某个对象。
if (value instanceof Array){
// 操作数组
}
let value = []
if (value instanceof Array) {
// 操作数组
console.log('value是数组')
} else {
console.log('value不是数组')
}
console.log(value instanceof Array)// true
2. Array.isArray()方法
ES5新增数组方法,判断数组是不是数组。
let value = []
if (Array.isArray(value)) {
console.log('value是数组')
} else {
console.log('value不是数组')
}
console.log(Array.isArray(value))// true
3. constructor
判断实例(arr)的构造函数是否等于某个对象。
let arr = [1,2,3];
console.log(arr.constructor == Array); //true
6. 迭代器方法(keys,values,entries)
1. keys()方法
返回数组索引的迭代器
const arr = ["foo", "bar", "baz", "qux"];
// 因为这些方法都返回迭代器,所以可以将它们的内容
// 通过 Array.from()直接转换为数组实例
const Keys = Array.from(arr.keys());
console.log(Keys); // [0, 1, 2, 3]
2. values()方法
返回数组元素的迭代器
const arr = ["foo", "bar", "baz", "qux"];
const Values = Array.from(arr.values());
console.log(Values); // ["foo", "bar", "baz", "qux"]
3. entries()方法
返回索引/值对的迭代器
const arr = ["foo", "bar", "baz", "qux"];
const Entries = Array.from(arr.entries());
console.log(Entries); // [[0, "foo"], [1, "bar"], [2, "baz"], [3, "qux"]]
使用 ES6 的解构拆分键/值对:
const arr = ["foo", "bar", "baz", "qux"];
for (const [index, item] of arr.entries()) {
console.log(item, index)
}
注意 虽然这些方法是 ES6 规范定义的,但在 2017 年底的时候仍有浏览器没有实现它们。
7. 复制和填充方法( copyWithin,fill)
1. 批量复制方法 copyWithin()
copyWithin()会按照指定范围浅拷贝数组中的部分内容,然后将它们插入到指定索引开始的位置
开始索引和结束索引则与 fill()使用同样的计算方法
- 从 arr 中复制索引 0 开始的内容,插入到索引 5 开始的位置
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 从 arr 中复制索引 0 开始的内容,插入到索引 5 开始的位置
// 在源索引或目标索引到达数组边界时停止
arr.copyWithin(5);
console.log(arr); // [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
- 从 ints 中复制索引 5 开始的内容,插入到索引 0 开始的位置
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 从 arr 中复制索引 5 开始的内容,插入到索引 0 开始的位置
arr.copyWithin(0, 5);
console.log(arr); // [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
- 从 arr 中复制索引 0 开始到索引 3 结束的内容,插入到索引 4 开始的位置
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.copyWithin(4, 0, 3);
console.log(arr); // [0, 1, 2, 3, 0, 1, 2, 7, 8, 9]
- JavaScript 引擎在插值前会完整复制范围内的值
// JavaScript 引擎在插值前会完整复制范围内的值
// 因此复制期间不存在重写的风险
arr.copyWithin(2, 0, 6);
console.log(arr); // [0, 1, 0, 1, 2, 3, 4, 5, 8, 9]
- 支持负索引值,与 fill()相对于数组末尾计算正向索引的过程是一样的
// 支持负索引值,与 fill()相对于数组末尾计算正向索引的过程是一样的
arr.copyWithin(-4, -7, -3);
console.log(arr); // [0, 1, 2, 3, 4, 5, 3, 4, 5, 6]
静默忽略超出数组边界、零长度及方向相反的索引范围:
- 索引过低,忽略
// 索引过低,忽略
arr.copyWithin(1, -15, -12);
console.log(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- 索引过高,忽略
arr.copyWithin(1, 12, 15);
console.log(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- 索引反向,忽略
arr.copyWithin(2, 4, 2);
console.log(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- 索引部分可用,复制、填充可用部分
arr.copyWithin(4, 7, 10)
console.log(arr); // [0, 1, 2, 3, 7, 8, 9, 7, 8, 9];
2. 填充数组方法 fill()
使用 fill()方法可以向一个已有的数组中插入全部或部分相同的值
- 用 5 填充整个数组:
zeroes.fill(5);
console.log(zeroes); // [5, 5, 5, 5, 5]
zeroes.fill(0); // 重置
console.log(zeroes); // [0, 0, 0, 0, 0]
- 用 6 填充索引大于等于 3 的元素
const zeroes = [0, 0, 0, 3, 3];
zeroes.fill(6, 3);
console.log(zeroes); // [0, 0, 0, 6, 6]
- 用 7 填充索引大于等于 1 且小于 3 的元素
const zeroes = [0, 0, 2, 3, 3];
zeroes.fill(8, -4, -1);
console.log(zeroes);//[0, 8, 8, 8, 3]
fill()静默忽略超出数组边界、零长度及方向相反的索引范围:
const zeroes = [0, 0, 0, 0, 0];
// 索引过低,忽略
zeroes.fill(1, -10, -6);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引过高,忽略
zeroes.fill(1, 10, 15);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引反向,忽略
zeroes.fill(2, 4, 2);
console.log(zeroes); // [0, 0, 0, 0, 0]
// 索引部分可用,填充可用部分
zeroes.fill(4, 3, 10)
console.log(zeroes); // [0, 0, 0, 4, 4]
8. 转换方法(valueOf,toString,join)
1. valueOf()方法
返回的还是数组本身
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
console.log(colors.valueOf()); // ['red', 'blue', 'green']
2. toString()方法
返回由数组中每个值的等效字符串拼接而成的一个逗号分隔的字符串
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
console.log(colors.toString()); // red,blue,green
3. join()方法
join()方法接收一个参数,即字符串分隔符,返回包含所有项的字符串
let colors = ["red", "green", "blue"];
console.log(colors.join("*")); // red*green*blue
console.log(colors.join("||")); // red||green||blue
注意: 如果数组中某一项是 null 或 undefined,则在 join()、toLocaleString()、toString()和 valueOf()返回的结果中会以空字符串表示。
9. 栈方法(push,pop)
1. push()方法
push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
let arr1 = Array()
console.log(arr1);//[]
arr1.push("red", "green")
arr1.push("brown"); // 再添加一项
arr1[3] = "black"; // 添加一项
console.log(arr1);//['red', 'green']
提示: 在数组起始位置添加元素请使用
unshift() 方法
。
2. pop()方法
pop()方法删除数组的最后一项,同时减少数组的 length 值,返回被删除的项。
let arr1 = Array()
console.log(arr1);//[]
arr1.push("red", "green")
arr1.push("brown"); // 再添加一项
arr1[3] = "black"; // 添加一项
arr1.pop() // ['red', 'green', 'brown']
console.log(arr1);//['red', 'green']
10. 队列方法(shift,unshift)
1. shift()方法
删除数组的第一项并返回它,然后数组长度减 1
let arr1 = new Array("red", "green")
arr1.shift()
console.log(arr1);// ['green']
2. unshift()方法
在数组开头添加任意多个值,然后返回新的数组长度
let arr1 = new Array("3", "4")
arr1.unshift('1', '2')
console.log(arr1);// ['1', '2', '3', '4']
通过使用 unshift()和 pop(),可以在相反方向上模拟队列,即在数组开头添加新数据,在数组末尾取得数据
let colors = new Array(); // 创建一个数组
let count = colors.unshift("red", "green"); // 从数组开头推入两项
alert(count); // 2
count = colors.unshift("black"); // 再推入一项,通过 unshift()填充数组
alert(count); // 3
let item = colors.pop(); // 取得最后一项,调用 pop()时,删除最后一项"green"并返回它。
alert(item); // green
alert(colors.length); // 2
11. 排序方法(reverse,sort)
1. reverse()方法
reverse()方法就是将数组元素反向排列
let arr1 = new Array()
arr1.unshift(1, 2, 3, 4, 5)
arr1.reverse() //[5, 4, 3, 2, 1]
console.log(arr1);
2. sort()方法
默认情况下,sort()会按照升序重新排列数组元素
调用 sort()会按照这些数值的字符串形式重新排序
sort()方法可以接收一个比较函数,用于判断哪个值应该排在前面。
let arr1 = new Array()
arr1.unshift(1, 2, 6, 4, 5, 3)
arr1.sort()
console.log(arr1)//[1, 2, 3, 4, 5, 6]
let arr2 = arr1.sort((a, b) => {
return b - a
})
console.log(arr2)//[6, 5, 4, 3, 2, 1]
注意 reverse()和 sort()都返回调用它们的数组的引用。
12. 操作方法(concat,slice)
1. concat()方法
concat ()方法用于连接两个或多个数组。
let arr1 = ["red", "green"];
let arr2 = arr1.concat("blue", "yellow", "purple")
console.log(arr2);//["red", "green","blue", "yellow", "purple"]
打平数组参数的行为可以重写,方法是在参数数组上指定一个特殊的符号:
Symbol.isConcatSpreadable
。这个符号能够阻止 concat()打平参数数组。相反,把这个值设置为 true 可以强制打平类数组对象:
let colors = ["red", "green", "blue"];
let newColors = ["black", "brown"];
let moreNewColors = {
[Symbol.isConcatSpreadable]: true,
length: 2,
0: "pink",
1: "cyan"
};
newColors[Symbol.isConcatSpreadable] = false;
// 强制不打平数组
let colors2 = colors.concat("yellow", newColors);
// 强制打平类数组对象
let colors3 = colors.concat(moreNewColors);
console.log(colors); // ["red", "green", "blue"]
console.log(colors2); // ["red", "green", "blue", "yellow", ["black", "brown"]]
console.log(colors3); // ["red", "green", "blue", "pink", "cyan"]
2. slice()方法
slice()方法创建一个包含原有数组中一个或多个元素的新数组
- slice()方法可以接收一个或两个参数:返回元素的开始索引和结束索引。
- 如果只有一个参数,则 slice()会返回该索引到数组末尾的所有元素。
- 如果有两个参数,则 slice()返回从开始索引到结束索引对应的所有元素,其中不包含结束索引对应的元素。
let arr1 = ["red", "green", "blue", "yellow", "purple"];
let arr2 = arr.slice(1);
let arr3 = arr.slice(1, 4);
alert(arr2); // green,blue,yellow,purple
alert(arr3); // green,blue,yellow
注意 :
- 如果 slice()的参数有负值,那么就以数值长度加上这个负值的结果确定位置。
比如,在包含 5 个元素的数组上调用 slice(-2,-1),就相当于调用 slice(3,4)。- 如果结束位置小于开始位置,则返回空数组。
- 删除
需要给 splice()传 2 个参数:要删除的第一个元素的位置和要删除的元素数量。可以从数组中删除任意多个元素,比如 splice(0, 2)会删除前两个元素。
let arr1 = ["red", "green", "blue"];
let removed = colors.splice(0, 1); // 删除第一项
alert(arr1); // green,blue
alert(removed); // red,只有一个元素的数组
- 插入
需要给 splice()传 3 个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数,乃至任意多个要插入的元素。
比如,splice(2, 0, “red”, “green”)会从数组位置 2 开始插入字符串"red"和"green"。
let arr1 = ["red", "green", "blue"];
removed = arr1.splice(1, 0, "yellow", "orange"); // 在位置 1 插入两个元素
console.log(arr1); // ['red', 'yellow', 'orange', 'green', 'blue']
console.log(removed);
- 替换
splice()在删除元素的同时可以在指定位置插入新元素,同样要传入 3 个参数:开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致。
比如,splice(2, 1, “red”, “green”)会在位置 2 删除一个元素,然后从该位置开始向数组中插入"red"和"green"。
let arr1 = ["red", "green", "blue"];
removed = arr1.splice(2, 1, "yellow", "orange"); // 在位置 1 插入两个元素
console.log(arr1); // ['red', 'green', 'yellow', 'orange']
console.log(removed);// ['blue']
13. 搜索和位置方法(indexOf,lastIndexOf,includes,find,findIndex)
ECMAScript 提供两类搜索数组的方法:按严格相等搜索和按断言函数搜索。
1. 严格相等(indexOf()、lastIndexOf()和 includes())
indexOf
()和includes()
方法从数组前头(第一项)开始向后搜索
lastIndexOf()
从数组末尾(最后一项)开始向前搜索。
indexOf()
和lastIndexOf()
都返回要查找的元素在数组中的位置,如果没找到则返回-1。
includes()
返回布尔值,表示是否至少找到一个与指定元素匹配的项。在比较第一个参数跟数组每一项时,会使用全等(===)比较,也就是说两项必须严格相等。
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(numbers.indexOf(4)); // 3
console.log(numbers.lastIndexOf(4)); // 5
console.log(numbers.includes(4)); // true
console.log(numbers.indexOf(4, 4)); // 5
console.log(numbers.lastIndexOf(4, 4)); // 3
console.log(numbers.includes(4, 7)); // false
let person = { name: "Nicholas" };
let people = [{ name: "Nicholas" }];
let morePeople = [person];
console.log(people.indexOf(person)); // -1
console.log(morePeople.indexOf(person)); // 0
console.log(people.includes(person)); // false
console.log(morePeople.includes(person)); // true
2. 断言函数(find()和 findIndex())
find()和 findIndex()方法使用了断言函数。这两个方法都从数组的最小索引开始。
find()
返回第一个匹配的元素
const people = [{ name: '张三疯', age: 23 }, { name: '史珍香', age: 21 }]
console.log(people)
let find = people.find((element, index, array) => element.age < 23)
console.log(find);//{name: '史珍香', age: 21}
findIndex()
返回第一个匹配元素的索引。这两个方法也都接收第二个可选的参数,用于指定断言函数内部 this 的值。
const people = [{ name: '张三疯', age: 23 }, { name: '史珍香', age: 21 }]
let findIndex = people.findIndex((element, index, array) => element.age < 23)
console.log(findIndex);// 1
找到匹配项后,这两个方法都不再继续搜索。
14. 迭代方法(every, filter,forEach,map,some)
1. every()方法
every方法与some方法相反,every方法是数组中的所有值都符合你给定的判断条件的时候才会返回true,否则就返回false。
let arr1 = [1, 2, 3].every(item => item >= 2)
let arr2 = [1, 2, 3].every(item => item <= 1)
console.log(arr1);// false
console.log(arr2);// true
2. filter()方法
“过滤”、“筛选”的意思。指数组filter后,返回过滤后的新数组。
函数返回 true 的项会组成数组之后返回,
0
为false
var arr1 = [1, 2, 3, 4];
var newArr = arr1.filter((item) => {
return item;
})
var newArr2 = arr1.filter((item) => {
return item >= 2;
})
// var newArr2 = arr.filter(e => e >= 2)
(简写,只有一个return语句时,将括号都去掉)
console.log(newArr); //
[1, 2, 3, 4]
console.log(newArr2); // [2, 3, 4]
3. forEach()方法
forEach 对数组的每个元素执行一次提供的函数
var arr = [1, 2, 3];
arr.forEach(function (element, index, array) {
console.log(element, index, array)
})
// output
1 0 [ 1, 2, 3 ]
2 1 [ 1, 2, 3 ]
3 2 [ 1, 2, 3 ]
forEach方法还可以传入第二个参数,这个参数是可选的。如果给forEach传递了第二个参数,callback函数里的this将指向这个参数。
注意:如果是箭头函数形式,那么第二个参数改变指向这种操作是无效的,因为箭头函数没有自己的this,它的this是继承而来。
4. map()方法
map方法的作用就是将原数组按照一定的规则映射成一个新的数组。再将其返回,是返回一个新的数组,而不是将原数组直接改变。使用方法和参数都跟forEach相似。
var arr1 = [1, 2, 3];
var newArr = arr1.map(function (element) {
return element * 2; // 需要有return
});
console.log(newArr); //[1, 4, 9]
5. some()方法
只要数组中的某个值,符合你给定的判断条件就返回true;否则,返回false。
let arr1 = [1, 2, 3].some(item => item >= 4)
let arr2 = [1, 2, 3].some(item => item <= 4)
console.log(arr1);// false
console.log(arr2);// true
15. 归并方法(reduce,reduceRight)
1. reduce()方法
reduce()方法从数组第一项开始遍历到最后一项
2. reduceRight()方法
reduceRight()从最后一项开始遍历至第一项
这两个方法都接收两个参数:对每一项都会运行的归并函数,以及可选的以之为归并起点的初始值。传给 reduce()和 reduceRight()的函数接收 4 个参数:上一个归并值
、当前项
、当前项的索引
和数组本身
。这个函数返回的任何值都会作为下一次调用同一个函数的第一个参数。如果没有给这两个方法传入可选的第二个参数(作为归并起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。
使用 reduce()函数执行累加数组中所有数值的操作
let arr1 = [1, 2, 3, 4, 5]
let sum = arr1.reduce((prev, item, index, array) => {
return prev + item
})
console.log(sum); //15
究竟是使用 reduce()还是 reduceRight(),只取决于遍历数组元素的方向。除此之外,这两个方法没什么区别。
最后
以上就是热心帆布鞋为你收集整理的JavaScript总结第1章 编程语言第2章 计算机基础第3章 什么是JavaScript第4章 HTML中的JavaScript第5章 语言基础第6章 基本引用类型第7章 集合引用类型的全部内容,希望文章能够帮你解决JavaScript总结第1章 编程语言第2章 计算机基础第3章 什么是JavaScript第4章 HTML中的JavaScript第5章 语言基础第6章 基本引用类型第7章 集合引用类型所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复