JavaScript(ECMAScript+DOM+BOM)

一. JavaScript基础

1. JavaScript初识

1. JavaScript是什么

JavaScript是一种运行在客户端的脚本语言(Script是脚本的意思)

脚本语言: 不需要编译,运行过程中由Js解释器(Js引擎)逐行来进行解释并执行。

现在也可以基于Node.js技术进行服务器端编程。

2. JavaScript的发展历史

布兰登艾奇(1961年~),在1995年利用10天时间完成JavaScript设计

网景公司最初命名位LiveScript,后来以Sun合作之后将其改名位JavaScript

注意:JavaScript与Java没有关系(就像雷峰塔与雷锋一样)

3. JavaScript的作用

表单动态检验(密码强度检测)(JS产生的最初的目的

网页特效

服务端开发(Node.js)

桌面程序(Electron)

APP(Cordova)

控制硬件-物联网(Ruff)

游戏开发(cocos2d-js)

4. 浏览器执行JavaScript的原理

浏览器分成两部分: 渲染引擎和JS引擎

渲染引擎: 用来解析HTML与CSS,俗称内核,比如chrome浏览器的blink,老版本的webkit

JS引擎: 也称为JS解释器。用来读取网页中的JavaScript代码,比如chrome浏览器的V8

浏览器本身并不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码

JS引擎执行代码时逐行解释每一句源码(转换位机器语言),然后由计算机去执行

所以JavaScript语言归为脚本语言,会逐行解释执行。

5. JavaScript由哪三部分组成

ECMAScript+DOM+BOM

ECMAScript,往往被称为JavaScript或JScript,实际上后两者是ECMAScript语言的实现和扩展。

注意:

ECMAScript:规定了JS编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。

DOM——文档对象模型,是W3C组织推荐的处理可扩展标记语言的标准编程接口。

通过DOM提供的接口可以对页面上的各种元素进行操作(大小,位置,颜色)

BOM——浏览器对象模型

它提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。

通过BOM可以操作浏览器窗口,比如弹出框,控制浏览器跳转,获取分辨率等。

6. JS有三种书写位置

分别为行内,内嵌和外部

1. 行内式

<input type=”button” value=”点我试试” onclick=”alert(‘Hello World’)”>

可以将单行或少量JS代码写在HTML标签的事件属性中(以on开头的属性)如:onlick

注意单双引号的使用:在HTML中,我们推荐使用双引号,JS中我们推荐使用单引号

可读性差,在html中编写JS大量代码时,不方便阅读

引号易错,引号多层嵌套匹配时,非常容易弄混;

特殊情况下使用

2. 内嵌式

<script>
    alert(‘hello world~!’)
</script>

3. 外部JS文件

<script src=”my.js”></script>

利用HTML页面代码结构化,把大段JS代码独立到HTML页面之外,既美观,也方便文件级别的复用。

引用外部JS文件的script标签中间不可以写代码

适合于JS代码量比较大的情况。

7. JavaScript注释

1. 单行注释 (//) (ctrl+/)

2. 多行注释(/* */) (shift+alt+a)

8. JS的三个输入输出语句

方法

说明

归属

alert(msg)

浏览器弹出警示窗

浏览器

console.log(msg)

浏览器控制台打印输出信息

浏览器

prompt(info)

浏览器弹出输入框,用户可以输入

浏览器

输出语法:

语法1:document.write(‘要输出的内容’)

作用:向body内输出内容

注意:如果输出的内容写的是标签,也会被解析成网页元素。

语法2:alert(‘要出的内容’)

作用:页面弹出警告对话框

语法3:console.log(‘控制台打印’)

作用:控制台输出语法,程序员调试使用

输入语法:

语法:prompt(‘请输入您的姓名:’)

作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字

JavaScript代码执行顺序:按HTML文档流顺序执行JavaScript代码

alert()和prompt()它们会跳过页面渲染先被执行

2. 编程语言

编程: 就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。

计算机程序:人类要控制计算机一定要通过计算机语言向计算机发出命令。

注意:上面所定义的计算机: 指的是任何能够执行代码的设备,可能是智能手机,ATM机,黑莓PI,服务器等等。

1. 计算机语言可以分为

机器语言,汇编语言和高级语言三大类

实际上计算机最终执行的都是机器语言,它是由“0”和“1”组成的二进制数。

二进制是计算机语言的基础。

汇编语言和机器语言实质是相同的,都是直接对硬件进行操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。

高级语言:并不是特指具体某一种语言,而是包括了很多编程语言,常用的有C语言,C—++,JAVA,C#,python,PHP,JavaScript等等

例如:C语言:puts(“你好”);PHP: echo”你好”;;Java: System.out.println(“你好”);

JavaScript: alert(“你好”);

2. 翻译器

高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器。

翻译器可以将我们所编写的源代码转换为机器语言,这也被称为二进制化。

3. 编程语言和标记语言区别

编程语言有很强的逻辑和行为能力,在编程语言里,你会看到很多if else,for,while,等具有逻辑性和行为能力的指令,这是主动的。

标记语言: 不用于向计算机发出指令,常用于格式化和链接。标记语言的存在是用来被读取的,他是被动的。

4. 计算机组成

硬件:

输入设备(鼠标,键盘,手写板,摄像头等)

输出设备(显示器,打印机,投影仪)

CPU(负责处理数据与运算)

硬盘(负责存储数据——永久存储数据)

内存(负责存储数据——暂时存储数据)

软件:

系统软件(Windows,linux,macOS)

应用软件(浏览器,QQ,HBuilder,Sublime,Word)

5. 数据存储

1. 计算机内部使用二进制0和1来表示数据

2. 所有数据,包括文件,图片等最终都是以二进制数据(0和1)的形式存放在硬盘中的

3. 所有程序,包括操作系统,本质都是各种数据,也是以二进制数据的形式存放在硬盘中。

(平时我们所说的安装软件,起始就是把程序文件复制到硬盘中)

6. 数据存储单位

bit< byte < kb <.<MB < GB < TB <……

位(bit):1bit可以保存一个0或1(最小的存储单位)

字节

Byte

1B=8b

千字节

KB

1KB=1024B

兆字节

MB

1MB=1024KB

吉字节

GB

1GB=1024MB

太字节

TB

1TB=1024GB

7. 程序运行

硬盘内存条CPU

1. 打开某个程序时,先从硬盘中把程序的代码加载到内存中

2. CPU执行内存中的代码

注意:之所以要内存的一个重要原因,是因为CPU运行太快了,如果只从硬盘中读数据,会浪费CPU性能,所以,才使用存取速度更快的内存来保存运行时的数据。(内存是电,硬盘是机械)

8. 变量

变量的主要作用:因为我们一些数据需要保存,所以需要变量

变量是什么:变量是一个容器,用来存放数据的,方便我们以后使用里面的数据

变量的本质:是程序在内存中申请的一块用来存放数据的空间。

变量使用时分为两步:1. 声明变量(var age;)2. 赋值(age=10;)

声明变量:要想使用变量,首先需要创建变量。

声明变量有两部分组成:声明关键字,变量名(标识)

语法:let 变量名

let即关键字(let:允许,许可,让,要),所谓关键字,是系统提供的专门用来声明(定义)变量的词语。

变量赋值:定义了一个变量后,你就能够初始化它(赋值)

变量的初始化(声明的同时直接赋值)

例如:let age=18

变量的更新:变量赋值后,还可以通过简单的给它一个不同的值来更新它。

同时声明多个变量:只需要写一个var,多个变量名之间使用英文逗号隔开

var age=10, name=’zs’, sex=2;

声明变量特殊情况

情况

说明

结果

var age; console.log(age)

只声明不赋值

underfined

console.log(age)

不声明不赋值直接使用

报错

age=10; console.log(age);

不声明只赋值

10

变量的命名规范:由字母,数字,下划线,美元符号组成,严格区分大小写,不能以数字开头

不能是关键字,保留字 例如var, for, while if,变量名必须有意义,遵循驼峰命名法。首字母小写,后面单词的首字母都需要大写。

注意:let不允许多次声明一个变量

正确写法(直接给值)

错误写法

let age = 18

let age = 18

age = 19

let age = 19

document.write(age)

document.write(age)

9. 常量

使用const声明的变量称为“常量”

使用场景:当某个变量永远不会改变的时候,就可以使用const来声明,而不是let

常量使用:

const G = 9. 8
console.log(G)

注意:常量不允许重新赋值,声明的时候必须赋值(初始化)

小技巧:不需要重新赋值的数据使用const

10. let和var区别

在较旧的JavaScript,使用关键字var来声明变量,而不是let

var现在开发中一般不再使用它,只是我们可能在老版的程序中看到它。

let为了解决var的一些问题。

var声明:可以先使用,再声明(不合理);var声明过的变量可以重复声明(不合理)

比如变量提升,全局变量,没有块级作用域等。

总结:var 就是个bug,以后声明变量我们统一使用let

11. 表达式和语句

区别:表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧

表达式:num = 3+4

语句:而语句不一定有值,比如alert()  for  和break等语句就 不能被用于赋值

3. 数据类型

JS是弱数据类型,变量到底属于那种类型,只有赋值之后,我们才能确认

计算机中,不同数据类型所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。

变量用来存储值的所在处,它们有名字和数据类型。

//这是一个数字型
var age=10;
//这是一个字符串
var areYouOK=’是的’;

代码运行时,变量的数据类型是由JS引擎根据=右边变量值的数据类型来判断的,运行完毕之后,变量就确定了数据类型。

JS把数据类型分为两类:

简单数据类型(Number,String,Boolean,Underfined,Null)

复杂数据类型(Object)

1. 5种简单的数据类型

简单数据类型

说明

默认值

Number

数字型,包含整数型和浮点型值,如21,0.21

0

Boolean

布尔值类型,如true,false,等价于1和0

false

String

字符串类型,如“张三”注意js里面,字符串都带引号

“”

Undefined

var a;声明了变量a但是没有给值,此时a=undefined

undefined

Null

var a=null;声明了变量a位空值

null

2. 数字型进制

number(数字型)

即我们数学中学到的数字(可以是整数,小数,正数,负数)

数字可以有很多操作,所以经常和算术运算符一起。

数学运算符也叫算术运算符,主要包括加,减,乘,除,取余(求模)

最常见的进制有:二进制,八进制,十进制,十六进制

数字型范围:

数字型最大值: console.log(Number.MAX_VALUE);

数字型最小值: console.log(Number.MIN_VALUE);

3. 数字型三个特殊值

Infinity,代表无穷大,大于任何数值

-Infinity,代表无穷小,小于任何数值

Nan,Not a number,代表一个非数值

isNan(),用于判断非数字。是“非数字”返回true,是“数字”则返回false。

4. 字符串型String

通过单引号’’,双引号””,或者反引号``包裹的数据都叫字符串,单引号和双引号没有本质的区别,推荐使用单引号。

字符串引号可以嵌套(单引号嵌套双引号,双引号嵌套单引号)

5. 字符串转义符

(类似于HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符)

转义符

解释说明

\n

换行符,n是newline的意思

\\

斜杠\

\’

‘单引号

\”

“双引号

\t

tab缩进

\b

空格,b是blank的意思

6. 字符串长度

通过字符串length属性获取整个字符串的长度

var strMsg= “我是大美女”;
alter(strMsg.length);//显示5

7. 字符串拼接

多个字符串之间可以使用+进行拼接,其拼接方式为字符串+任何类型=拼接之后的新字符串

字符串拼接加强

我们经常会将字符串和变量来拼接,因为变量可以很方便地修改里面的值。

即变量不要写到字符串里面,是通过和字符串相连的方式实现的。

8. 布尔型Boolean

布尔型有两个值:true和false,其中true表示真(对),而false表示假(错)

参与运算时,true表示1,false表示0

9. Undefined和Null

undefined(未定义型),只声明变量,不赋值的情况下,变量的默认值为undefined,一般很少直接为某个变量赋值为undefined。

null(空类型),如果一个变量里面确定存放的是对象,如果还没准备好对象,可以放个null。

undefined表示没有赋值,null表示赋值了但是内容为空。

10. 获取变量数据类型

typeof可用来获取检测变量的数据类型

例如:console.log(typeof 变量名);

1. 可以通过chrome控制台输出内容的颜色判断数据类型

2. 字面量(在源代码中一个固定值的表示法)

11. 数据类型的转换

方式

说明

案例

toString()

转成字符串

var num=1;alert(num.toString())

String()强制转换

转成字符串

var num=1;alert(String(num));

加号拼接字符串

和字符串拼接的结果都是字符串

var num=1;alert(num+”字符串”);

隐式转换:某些运算符被执行时,系统内部将自动将数据类型进行转换。

+号两边只要有一个是字符串,都会把另外一个转成字符串。除了+以外的算术运算符,比如-*/等都会把数据转成数字类型

缺点:转换类型不明确,得靠经验才能总结

技巧:+号作为正号解析可以转换成字符型,任何数据和字符串相加结果都是字符串。

显式转换:自己写代码告诉系统该转成什么类型

转换为数值型:Number(数据)

只保留整数:parseInt(数据)

可以保留小数:parseFloat(数据)

方式

说明

案例

parselnt(string)函数

将string类型转换为整数数值型

parselnt(‘78’)

parseFloat(string)函数

将string类型转换为浮点数数值型

parseFloat(‘78.21’)

Number()强制转换函数

将string类型转换为数值型

Number9(‘12’)

js隐式转换(-*/)

利用算术运算隐式转换为数值型

‘12’-0

转换为布尔型

方式

说明

案例

Boolean()函数

其他类型转成布尔值

Boolean(‘true’)

代表空的,否定的值会被转换为false,其余的值都会被转换为true

12. 扩展

1. 解释型语言和编译型语言

翻译器将程序语言翻译成机器语言

翻译器翻译的方式有两种:一个是编译,另一个是解释。两种方式的区别在于翻译的时间点不同。

编译器是在代码执行之前进行编译,生成中间代码文件

解释器是在运行时进行解释,并立即执行。(当编译器以解释方式运行的时候,也称之为解释器)

2. 标识(zhi)符,关键字,保留字

标识符:指开发人员为变量,属性,函数,参数取的名字。

关键字:指JS本身已经使用了的名字,不能再用它们充当变量名,方法名。

保留字: 实际上就是预留的关键字,意思是现在虽然还不是关键字,但未来可能会成为关键字,同样不能使用它们当变量名或方法名。

13. 数据传参

1. 简单数据类型如何传参

函数的形参也可以看做是一个变量,

当我们把一个值类型变量作为参数传给函数的形参时,

其实是把变量在栈空间里面的值复制给形参,

那么在方法内部对形参做任何修改,都不会影响到外部变量

2. 复杂数据类型如何传参

函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,

其实是把变量在栈空间里保存的堆地址复制给了形参,

形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象

3. 简单类型和复杂类型

简单数据类型(基本数据类型或值类型)

在存储变量中存储的是值本身,因此叫做值类型

复杂类型(引用类型)

在存储变量时存储的仅仅是地址,因此叫做引用数据类型

通过new关键字创建的对象(系统对象,自定义对象)

4. 堆和栈

栈:由操作系统自动分配释放存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;

简单数据类型存放到栈里面

堆:存储复杂类型(对象),一般由程序员释放,若程序员不释放,由垃圾回收机制回收。

引用数据类型存放到堆里面

14. 模板字符串

使用场景:拼接字符串和变量

在没有它之前,要拼接字符串比较麻烦

document.write(‘大家好,我叫’+name+’,今年’+age+’岁’)

语法:``(反引号)

在英文输入模式下按键盘的tab键上方那个键,内容拼接变量时,用${}包住变量。

document.write(`我今年${age}岁了`)

4. 运算符

运算符,也称操作符,用于实现赋值,比较和执行算数运算等功能的符号。

1. 算数运算符

运算符

描述

实例

+

10+10=20

-

10-20=-10

*

10*20=200

/

10/20=0.5

%

取余数(取模)

9%2=1(返回除法的余数)

2. 递增和递减运算符

递增(++)和递减(--)运算符

递增(++)和递减(--)既可以放在前面,也可以放在变量后面。

放在变量前面时,我们称为前置递增(递减)运算符(先自增,后返回值)

放在变量后面时,我们可以称为后置递增(递减)运算符(先返回值,再自增)

3. 比较运算符

返回一个布尔值

==:左右两边值是否相等

===:左右两边是否类型和值都相等

!==:左右两边是否不全等

运算符名称

说明

案例

结果

<

小于号

1<2

true

>

大于号

1>2

false

>=

大于等于号

2>=2

false

<=

小于等于号

3<=2

false

==

判等号(会转型)

37==37

true

!=

不等号

37!=37

false

===   !==

全等 要求值和数据类型都一致

37===’37’

false

4. 逻辑运算符

使用场景:逻辑运算符用来解决多重条件判断

用来进行布尔值运算的运算符,其返回值也是布尔值。&&,||,!

短路运算的原理(当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续运算右边表达式的值)。

逻辑与

语法:表达式1&&表达式2

如果第一个表达式的值为真,则返回表达式2

如果第一个表达式的值为假,则返回表达式1

逻辑或

如果第一个表达式的值为真,则返回表达式1

如果第一个表达式的值为假,则返回表达式2

5. 赋值运算符

用来把数据赋值给变量的运算符

赋值运算符

说明

案例

=

直接赋值

var userName=’我是值’

+=,-=

加,减一个数,后再赋值

var age=10;age+=5;//15

*=,/=,%=

乘,除,取模 后再赋值

var age=2; age*=5;//10

6. 运算符优先级

目标:掌握运算符优先级,能判断运算符执行顺序

优先级

运算符

顺序

1

小括号

()

2

一元运算符

++  --  !

3

算数运算符

先*/%后+-

4

关系运算符

>  >=  <  <=

5

相等运算符

==  !=  ===  !==

6

逻辑运算符

先&&  后||

7

赋值运算符

=

8

逗号运算符

5. 数组

之前学习的变量,只能存储一个值。

如果我们想要存储班级中所有学生的姓名,则可以使用数组。

数组可以把一组相关的数据一起存放,并提供方便的获取方式。

操作数组:数组本质是数据集合,操作数据无非就是增 删 改 查

1. 创建数组

JS中创建数组有两种方式:

1. 利用new创建数组

var 数组名= new Array();

var arr = new Array();(创建一个新的空数组)

2. 利用数组字面量创建数组(更常用些)

let 数组名 = [数据1,数据2,...,数据n]

例如:let names = [ ‘小明’, ’小刚’, ’小红’, ’小丽’, ’小米’]

声明数组并赋值称为数组的初始化

注意:数组里面的数据一定要用逗号分隔。

数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。

2. 获取数组中的元素

索引(下标):用来访问数组的序号(数组下标从0开始

数组名[索引号]

例如:console.log(arr[0])   (打印出来的是小明)

3. 对数组进行遍历

利用循环

所谓的遍历,就是把数组中的每个元素从头到尾都访问一次。

4. 数组的长度

数组名.length(可以访问数组元素的长度)

5. 给数组新增一个元素

可以通过修改length长度以及索引号增加数组元素

增:arr.push(新增的内容)//在后面加   arr.unshift(新增的内容)//在前面加

1. 通过修改length长度新增数组元素(length属性可读写):arr.length = 想要的长度;

2. 通过修改数组索引新增数组索引:arr[追加数据的索引]=’追加的数据’;

6. 删除数组元素

arr.pop()//删除最后一个元素,会返回删除的元素

arr.shift()//删除第一个元素

arr.splice(操作的下标,删除的个数)

7. 数组排序(冒泡排序)

这是一种算法,把一系列数据按照一定的顺序进行排序显示(从小到大或从大到小)

例如将数组[5,4,3,2,1]中的元素按照从小到大的顺序排序,输出:1,2,3,4,5

1. 一共需要的趟数,我们用外层for循环(趟数就是arr.length-1)

2. 每一趟交换的次数,我们用里层for循环(次数是(arr.length-i-1)

3. 交换两个变量即可

数组排序:数组.sort()方法可以排序

6. 函数

函数:就是封装了一段可被重复调用执行的代码块。通过此代码可以实现大量代码的重复使用。

比如我们前面使用的alert(),prompt()和console.log()都是一些js函数,只不过已经封装好了,我们直接使用。

函数的使用:1. 声明函数;2. 调用函数

1. 声明函数

function 函数名() {
    //函数体
}

(函数是做某件事,函数名一般是动词)

(函数如果不调用,自己是不会执行的)

2. 调用函数

函数名();

3. 函数的封装

就是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。

4. 函数的参数

函数传参-参数默认值

形参:可以看做变量,但是如果一个变量不给值,默认是什么?undefined

我们可以改进一下,用户不输入实参,可以给形参默认值,可以默认为0。

注意:这个默认值只会在缺少实参参数传递时,才会被执行,所以有参数会优先执行传递过来的参数,否则默认为undefined。

function getSum(x=0,y=0) {
    document.write(x+y)
}
//这样结果是0,而不是N
getSum()
//结果是3  
getSum(1,2) 

函数的参数分为形参和实参

function 函数名(形参1,形参2...){   //在声明函数的小括号里面,是形参 }

函数名(实参1,实参2...){   //在函数调用的小括号里,是实参 }

参数

说明

形参

形式上的参数,函数定义的时候 传递的参数,当时并不知道是什么

实参

实际上的参数,函数调用的时候传递的参数 实参是传递给形参的

5. 形参和实参个数不匹配

在Javascript中,实参的个数和形参的个数可以不一致

1. 如果形参过多,会自动填充上undefined

2. 如果实参过多,那么多余的实参会被忽略

参数个数

说明

实参个数等于形参个数

输出正确结果

实参个数多于形参个数

只取到形参的个数

实参个数小于形参个数

多的形参定义为undefined,结果为NaN

6. 函数的返回值

在函数体中使用return关键字能将内部的执行结果交给函数外部使用

函数只是实现某种功能,最终的结果需要返回给函数的调用者(函数名())

只要函数遇到return就把后面的结果,返回给函数的调用者。函数名()=return后面的结果

function getResult() {
    return 666;
}

getResult(); //getResult()=666

7. return终止函数

return语句之后的代码不被执行

函数如果有return,则返回的是return后面的值,如果函数没有return,则返回undefined

8. break,continue,return区别

break:结束当前的循环体(如for,while)

continue:跳出本次循环,继续执行下次循环(如for,while)

return: 不仅可以退出循环,还能够返回return语句中的值,同时还可以结束当前函数体内的代码。

9. arguments的使用

(只有函数才有arguments对象)

当我们不确定有多少个参数传递的时候,可以用arguments来获取。

在JS中,arguments实际上是当前函数的一个内置对象所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参

arguments展示形式是一个伪数组。(即 可以遍历)

特点:

1. 具有length属性

2. 按索引方式存储数据

3. 不具有数组的push,pop等方法

10. 函数的声明方式

1. 利用函数关键字自定义函数(命名函数)

function fn() {

}

fn();

2. 函数表达式(匿名函数)

var 变量名 = function() { };     //函数表达式声明方式根声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数

var fun = function() { //fun是变量名,不是函数名

}

fun();

没有名字的函数,无法直接使用

使用方式:

1. 函数表达式

将匿名函数赋值给一个变量,并且通过变量名称进行调用,我们将这个称为函数表达式

语法:

let fn=function(){
    //函数体
}
// 函数调用
fn()

函数表达式与具名函数的区别:具名函数的调用可以写到任意位置,但是函数表达式必须是先声明函数表达式,后调用。

2. 立即执行函数(场景介绍:避免全局变量的污染)

语法:

(function() {console.log(11)} ) ()

(function() {console.log(22)} () )

7. 内置对象

JavaScript中的对象分为三种:自定义对象;内置对象;浏览器对象

前面两个对象是JS基础内容,属于ECMAScript;第三个浏览器对象属于我们JS独有的,我们JS API讲解。

内置对象最大的优点就是帮助我们快速开发

JavaScript提供了多个内置对象:Math,Date,Array,String等

根据文档查询指定API

学习一个内置对象,只要学会其常用成员即可,我们可以通过查阅文档学习,可以通过MDN/W3C来查询。

MDN提供了有关开放网络技术的信息,包括HTML,CSS,和万维网及HTML5应用的API。

MDN: http://developer.mozilla.org/zh-CN/

1. 查阅该方法的功能

2. 查看里面参数的意义和类型

3. 查看返回值的意义和类型

4. 通过demo进行测试

1. Math对象

Math数学对象,不是一个构造函数,所以我们不需要new来调用,而是直接使用里面的属性和方法即可。

Date(日期)对象

是一个构造函数,必须使用new来调用创建我们的日期对象,获取日期总的毫秒数:

注意:Date对象是基于1970年1月1日(世界标准时间)起的毫秒数

Math对象包含的方法有:

random生成0-1之间的随机数(包括0不包含1)
ceil向上取整
floor向下取整
max找最大值
min找最小值
pow幂运算
abs绝对值

1. 取0-10之间的整数:Math.floor(Math.random()*(10+1))

2. 例如抽取数组中的一个数

let arr=[‘red’,’green’,’blue’]

let random=Math.floor(Math.random()*arr.length)

console.log(arr[random])

3. 取5-10之间的随机数:Math.floor(Math.random()*(5+1))+5

4. 取N-M之间的随机数:Math.floor(Math.random()*(M-N+1))+N

2. Array(数组)对象

检测是否为数组的两种方式:

1. instanceof 运算符号

例如: console.log(arr instanceof Array)

2. Array.isArray(参数)    H5新增的方法 ie9以上版本支持

例如: console.log(Array.isArray(arr));

3. 添加删除数组元素的方法

方法名

说明

返回值

push(参数,..)

末尾添加一个或多个元素,注意修改原数组

pop()

删除数组最后一个元素,把数组长度减1 无参数

unshift(参数1,...)

向数组开头添加1个或多个元素

shift()

删除数组的第一个元素,数组长度减1无参数,修改原数组

4. 返回数组元素索引

indexOf();,   lastIndexOf();

5. 数组转换为字符串

1. toString()

2. join(分隔符)

6. 基本包装类型

JavaScript提供了三个特殊的引用类型(String,Number,和Boolean

把简单数据类型包装成复杂数据类型,这样基本数据类型就有了属性和方法

7. String(字符串)对象

字符串的不可变性:指的是里面的值不可变,瑞士看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

字符串所有的方法,都不会修工资字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。

根据字符返回位置

方法名

说明

indexOf(‘要查找的字符’,’开始的位置’)

返回指定内容在原字符串中的位置,如果中不到就返回-1,开始的位置是index索引

lastIndexOf()

从后往前找,只找第一个匹配的

根据位置返回字符(重点)

方法名

说明

使用

charAt(index)

返回指定位置处的字符(index字符串的索引号)

str.charAt(0)

charCodeAt(index)

获取指定位置处字符的ASCII码(index索引号)

str.charCodeAt(0)

str[index]

获取指定位置处字符

HTML5,ie8+支持和charAt()等效

8. 字符串操作方法

方法名

说明

concat(str1,str2,str3...)

concat()方法用于连接两个或多个字符串。拼接字符串,等效于’+’,+更常用

substr(start,length)

从start位置开始(索引号),length取的个数

slice(start.end)

从start位置开始,截取到end位置,end取不到

substring(start,end)

从start位置开始,截取到end位置,end取不到,基本和slice相同,但是不接受负值

替换字符 replace(‘被替换的字符’, ‘替换为的字符’)

注意:它只会替换第一个字符

字符转换为数组 split(‘分隔符’)

var str2=’red,pink,blue’;
console.log(str2.split(‘ , ’);

var str3=’red&pink&blue’;
console.log(str3.split(‘&’);

8. 对象

1. 对象是一个具体的事物

对象(object):是JavaScript里的一种数据类型

可以理解为一种无序的数据集合(注意数组是有序的数据集合)

所有的事物都是对象例如字符串,数值,数组,函数等。明星不是一个对象,周星驰是一个对象

例如:

let obj={
    uname:’pink老师’,
    age:18,
    gender:’女’
}

对象声明语法:

let 对象名={}

let 对象名=new Object()

2. 对象由属性和方法组成

属性:事物的特征,在对象中用属性来表示(常用名词)

方法:事物的行为,在对象中用方法来表示(常用动词)

3. 为什么需要对象

保存一个值时,可以使用变量;保存多个值(一组值)时,可以使用数组;

如果想要保存一个人的完整信息呢?

例如:将“张三丰”的个人信息保存在数组中的方式为:

var arr=[‘张三丰’,‘男’,128,154];

JS中的对象表达结构更清晰,更强大

张三丰.姓名 = ‘张三丰’;

张三丰.性别 = ‘男’;

张三丰.年龄 = 128;

张三丰.身高 = 154;

4. 三种方式创建对象(object)

1. 利用字面量创建对象

const o={
    name:’佩奇’
}

2. 利用new Object创建对象

const o= new Object ({name:’佩奇’})
console.log(o)  
// {name:’佩奇’}

3. 利用构造函数创建对象

5. 为什么需要使用构造函数

前面两种创建对象的方式一次只能创建一个对象。

而一次创建一个对象,里面很多的属性和方法是大量相同的,我们只能复制 

因此,我们可以利用函数的方法,重复这些相同的代码。这个函数,就叫构造函数。

这个函数的不一样之处在于,里面封装的不是普通代码,而是对象。

构造函数就是把我们对象里面一些相同的属性和方法抽象出来,封装到函数里面。

function 构造函数名() {
    this.属性=值;
    this.方法=function(){}
}

new 构造函数名();

构造函数:如Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类

创建对象:如naw Stars(),特指某一个,通过New关键字创建对象的过程我们也称对象的实例化。

6. 变量,属性,函数,方法

1. 变量和属性的相同点: 他们都是用来存储数据的。

var num=10;
var obj= {
    age=18
}

2. 变量和属性的不同点:

变量 //单独声明并赋值 使用的时候直接写变量名

属性 //在对象里面的,不需要声明; 使用的时候必须是 对象.属性

3. 函数和方法的相同点: 他们都是用来实现某种功能

4. 函数和方法的不同点:

函数 //单独存在 通过”函数名()”的方式就可以调用

方法 //在对象里面的, 使用的时候必须是 对象.方法()

7. new关键字

new关键字执行过程

1. new(构造函数可以在内存中创建了一个空的对象)

2. this就会指向刚才创建的空对象

3. 执行构造函数里面的代码,给这个空对象添加属性和方法

4. 返回这个对象

8. 遍历对象属性

for (var k in obj) {
    console.log(k); //k变量,输出得到的是属性名
    console.log(obj[k]); //obj[k]得到的是属性值
}

9. 作用域

通常来说,一段程序代码中,所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

目的是为了提高程序的可靠性,更重要的是减少命名冲突

JS的作用域(es6)

可以分为两种:全局作用域,局部作用域

1. 全局作用域

整个script标签 或者是一个单独的JS文件。函数外部或者整个script有效

例如;var num = 10;

2. 局部作用域(函数作用域)

也称函数作用域,这个代码的名字只在函数内部起效果和作用。

例如:

function fn() {
    //局部作用域
    var num = 20;
}

3. 变量的作用域

根据作用域的不同,变量可以分为两种

全局变量(即在全局作用域下的变量)局部变量(即在局部作用域下的变量)

注意:局部变量或者块级变量,没有let声明直接赋值的,当全局变量看。

函数的形参,也可以看作局部变量。

从执行效率来看,全局变量只有浏览器关闭的时候才会销毁,比较占内存资源;局部变量当程序执行完毕就会销毁,比较节约内存资源。

JS中没有块级作用域(在es6中才有块级作用域)

4. 作用域链

只要是代码,就会有作用域。

根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。

5. 变量的访问原则

只要是代码,就至少有一个作用域。

写在函数内部的局部作用域,如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域

访问原则:在能够访问到的情况下,先局部,局部没有再找全局

10. JavaScript流程控制

即控制代码按照什么结构顺序来执行。

流程控制主要有三种结构,分别是顺序结构,分支结构,循环结构

1. 顺序结构

是程序中最简单的,最基本的流程控制,没有特定的语法结构,程序会按照代码的先后顺序,依次执行

2. 分支结构

1. 分支流程控制if语句

由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果。

js语言提供了两种分支结构语句:if语句  switch语句

if (条件表达式) {
    条件成立执行的代码语句
}

(如果if里面的条件表达式为真,则执行大括号里面的执行语句)

(如果if里面的条件表达式为假,则执行if语句后面的代码)

if else语句(双分支语句)

if (条件表达式) {
    //如果条件成立执行的代码
} else {
    //否则执行的代码
}

if elae if 语句(多分支语句)

if (条件表达式1) {
    //条件表达式1成立执行的代码
} else if (条件表达式2) {
    //条件表达式2成立执行的代码
} else {
    //以上条件都不满足时执行的代码
}

2. 三元表达式

?:

条件表达式?表达式1:表达式2

如果条件表达式结果为真,则返回表达式1的值,如果条件表达式结果为假,则返回表达式2的值

3. 分支流程控制switch语句

当要针对变量设置一系列的特定值的选型时,就可以使用switch

switch (表达式) {
    case value1;
    //表达式等于value1时要执行语句1;
    break;
    case value2;
    //表达式等于value2时要执行语句1;
    break;
    ...
    default:
    // 执行最后的语句;
}

在开发中,我们经常将表达式写成变量;

表达式的值与value的值相匹配的时候,是全等的关系。(值和类型都得一样)

注意:没有break的时候发生的case穿透现象。

4. switch语句和if else if 语句的区别

1. 一般情况下,它们两个语句可以相互替换

2. switch...case语句通常处理case为比较确定值的情况,而if else 语句更加灵活,常用于范围判断

3. switch语句进行条件判断后直接执行到程序的条件语句,效率更高。而if else语句有几种条件就得判断多少次。

4. 当分支比较少的时,if else语句的执行效率比switch语句高

5. 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。

3. 循环结构

循环的目的:在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句。

js中的循环主要有三种:for循环,while循环,do-while循环

1. for循环

for (初始化变量; 条件表达式; 操作表达式) {
    //循环体
}

初始化变量 就是用var声明的一个普通变量,通常用于作为计数器使用

条件表达式,循环终止的条件

操作表达式,用于更新我们计算器变量

for循环的执行过程

先执行初始化变量(这句话在for循环里面只会执行一次)

然后执行条件表达式,接着执行循环体,最后执行操作表达式,接着又执行条件表达式,又执行循环体。

断点调试观察代码的执行过程

断点调试是指自己在程序某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试。

步骤:

1. 浏览器按住F12-->sources-->找到需要调试的文件-->在程序的某一行设置断点

2. Watch:监视,通过Watch可以监视变量的值的变化

3. F11:程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的变化

注意:代码调试能力非常重要,只有学会了代码调试,才能学会自己解决bug的能力。

双重for循环

即循环的嵌套,在for循环语句中,可以再嵌套一个for循环。

可以把里面的循环看作是外层循环的语句

外层循环执行一次,里面的循环就会全部执行一次

2. while循环

while (条件表达式) {
    //循环体代码
}

执行思路:

1. 先执行条件表达式,如果结果为true,则执行循环体代码;如果为false,则退出循环

2. 执行循环体代码

3. 循环体代码执行完毕后,程序会继续判断执行条件表达式(重复步骤1)

注意:while循环里面,应该也有计数器(初始化变量),里面应该也有操作表达式(完成计数器的更新,防止死循环)。

3. do while循环

会先执行一次代码块,然后对条件表达式进行判断。

如果条件为真,就会重复执行循环体,否则退出循环。

do {
    //循环体代码(条件表达式为true时重复执行循环体代码
} while(条件表达式);

注意:do-while循环语句至少会执行一次循环体代码

4. break

该关键字用于立即跳出整个循环(循环结束)

5. continue

该关键字用于立即跳出本次循环,执行下一次循环(即本次循环体中,continue之后的代码就会少执行一次)

6. 命名规范以及语法格式

变量,函数的命名必须要有意义

变量的名称一般用名词,函数的名称一般用动词。

操作符的左右两侧各保留一个空格。

单行注释:单行注释前面注意有一个空格

二. WebAPI

1. API和Web API

1. API是什么

API(应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

简单理解:API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。

我们会使用就可以了,不必纠结内部如何实现。

声明变量有三个var let和const。建议:const优先,尽量使用const。

原因是:const语义化更好

很多变量我们声明的时候就知道他不会改变了,那为什么不用const呢

实际开发中也是,比如react框架,基本const

如果依然很纠结,建议:有了变量先给const,如果发现它后面是要被修改的,再改为let

document对象:是DOM里面提供的一个对象

它提供的属性和方法都是用来访问和操作网页内容的(例如:document.write()

网页所有内容都在document里面

对象是引用类型,里面存储的是地址,只要地址不变,就不会报错。建议数组和对象使用const来声明

2. WebAPI是什么

WebAPI的作用和分类

作用:就是使用JS去操作html和浏览器

分类:DOM(文档对象模型),BOM(浏览器对象模型)

WebAPI一般都有输入和输出(函数的传参和返回值),WebAPI很多都是方法(函数)

2. 本地存储

以前我们写的页面一刷新就没有了。

会经常性在本地存储大量的数据,HTML规范提出了相关解决方案。

1. 数据存储在用户浏览器中

2. 设置,读取方便,甚至页面刷新不丢失数据

3. 容量较大,session Storage和localStorage约5M左右

1. 本地存储特性

1. 数据存储在用户浏览器中

2. 设置,读取方便,甚至页面刷新不丢失数据。

3. 容量较大,sessionStrong约5M,localStorage约20M

4. 只能存储字符串,可以将对象JSON.stringify()编码后存储

2. window.sessionStorage

1. 生命周期为关闭浏览器窗口

2. 在同一个窗口(页面)下数据可以共享

3. 以键值对的形式存储使用

3. 存储数据

sessionStorage.setltem(key,value)

4. 获取数据

sessionStorage.getItem(key)

5. 删除数据

sessionStorage.removeItem(key)

6. 删除所有数据

sessionStorage.clear()

7. window.localStorage

1. 生命周期永久生效,除非手动删除,否则关闭页面也会存在

2. 可以多窗口(页面)共享(同一浏览器可以共享)

3. 以键值对形式存储

8. 存储数据

localStorage.setltem(key,value)

9. 获取数据

localStorage.getItem(key)

10. 删除数据

localStorage.removeItem(key)

11. 删除所有数据

localStorage.clear()

12. 存储复杂数据类型

本地只能存储字符串,无法存储复杂数据类型

const goods={
    name:’小米10’,
    price:1999
}
//返回的键是goods,返回的值是[object Object]
localStorage.setItem(‘goods’,goods)   

解决方法:需要将复杂数据类型转换成JSON字符串,再存储到本地

语法:JSON.stringify(复杂数据类型)

const goods={
    name:’小米10’,
    price:1999
}
localStorage.setItem(‘goods’,JSON.stringify(goods))

本地存储里面取出来的是字符串,不是对象,无法直接使用

解决:把取出来的字符串转换为对象

语法:JSON.parse(JSON对象)

const obj=JSON.parse(localStorage.getItem(‘good’))
console.log(obj)

13. 记住用户名案例

1. 把数据存储起来,用到本地存储

2. 关闭页面,也可以显示用户名,所以用到localStorage

3. 打开页面,先判断是否有这个用户名,如果有,就在表单里面显示用户名,并且勾选复选框。

4. 当复选框发送改变的时候change事件

5. 如果勾选,就存储,否则就移除

3. DOM

1. 什么是DOM

文档对象模型(DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口

W3C以及定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容,结构和样式。

DOM对象:浏览器根据HTML标签生成的js对象,所有的标签属性都可以再这个对象上面找到

修改这个对象的属性会自动映射到标签身上。

DOM作用:开发网页特效和实现用户交互

2. DOM树

文档:一个页面就是一个文档,DOM中使用document表示

元素:页面中的所有标签都是元素,DOM中使用element表示

节点:网页中的所有内容都是节点(标签,属性,文本,注释等),DOM中使用node表示

DOM把以上内容都看作是对象

DOM树:将HTML文档以树状结构直观的表现出来,我们称之为文档树或DOM树。是描述网页内容关系的名词。

作用:文档树直观的体现了标签与标签之间的关系

3. 获取页面元素

1. 根据ID获取

使用getElementByld()方法可以获取带有ID的元素的对象

参数id是大小写敏感字符串

返回的是一个元素对象

2. 根据标签名获取

使用getElementsByTagName()方法可以返回带有指定标签名的对象集合

使用element.getElementByTagName()方法获取某个元素(父元素)内部所有指定标签名的子元素。

注意:父元素必须是单个对象(必须指明是哪一个元素的对象)获取的时候不包括父元素自己。

3. 通过HTML5新增方法获取

1. document.getElementsByClassName(‘类名’);//根据类名返回元素对象集合

2. document.querySelector(‘选择器’)’ //根据指定选择器返回第一个元素对象

3. document.querySelectorAll(‘选择器’); //根据指定选择器返回

4. 特殊元素获取

1. 获取body元素

2. 获取html元素

4. 事件基础

JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。

简单理解就是: 触发——响应机制

常见的鼠标事件

鼠标事件

触发事件

onclick

鼠标点击左键触发

onmouseover

鼠标经过触发

onmouseout

鼠标离开触发

onfoucus

获得鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmousedown

鼠标按下触发

onmouseup

鼠标弹起触发

5. 操作元素

DOM操作可以改变网页内容,结构和样式。

我们利用DOM操作元素来改变元素里面的内容,属性等

1. 修改普通元素内容

//从起始位置到终止位置的内容,但它去除(不识别)html标签,同时空格和换行也会去掉

element.innerText   

//起始位置带终止位置的全部内容,包括(识别)html标签,同时保留空格和换行

element.innerHTML

2. 修改常见元素的属性操作

1. innerText,innerHTML改变元素内容

2. src,href

3. id,alt,title

3. 修改表单元素的属性操作

type , value, checked, selected, disabled

4. 修改元素样式属性操作

通过JS修改元素的大小,颜色,位置等样式

1. element.style  //行内样式属性

语法:对象.style.样式属性=值

2. element.className类名样式属性

注意:如果样式修改较多,可以采取操作类名方式更改元素样式

语法:元素.className=’active’

注意:class是关键字,因此使用className来操作元素类名属性

className是使用新值换旧值,会覆盖原先的类名。

3. 通过classList操作类控制css

为了解决className容易覆盖以前的类名,我们可以通过classList方式追加和删除类名

语法:(注意,类名前面不要加‘点’)

//追加一个类
元素.classList.add(‘类名’)

//删除一个类
元素.classList.remove(‘类名’)

//切换一个类
元素.classList.toggle(‘类名’)

5. 排他思想

如果有同一组元素,我们想要实现某种样式,即可用到循环的排他思想算法:

1. 所有元素全部清除样式

2. 给当前元素设置样式

3. 注意顺序不能颠倒

6. 自定义属性的操作

1. 获取属性值

1. element.属性

2. element.getAttribute(‘属性’);

区别:

element.属性(获取内置属性值(元素本身自带的属性))

element.getAttribute(‘属性’); (主要获得自定义的属性(标准)我们程序员自定义的属性)

2. 设置属性值

1. element.属性=‘值’(设置内置属性值)

2. element.setAttribute(‘属性’,’值’);  (主要针对于自定义属性)

3. 移除属性

removeAttribute(属性)

7. H5自定义属性

自定义属性目的:是为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中

自定义属性获取是通过getAttribute(‘属性’)获取

但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性

H5给我们新增了自定义属性

1. 设置H5自定义属性

H5规定自定义属性data-开头作为属性名并且赋值

例如<div data-index=”1”></div>

或者用JS设置:element.setAttribute(‘data-index’,2)

2. 获取H5自定义属性

兼容性获取: element.getAttribute(‘data-index’);

H5新增element.dataset.index或者element.dataset[‘index’] ie11才支持

<body>
    <div class=”box” data-id=”10”>盒子</div>

<script>
    const box=document.querySelector(‘.box’)
    console.log(box.dataset.id)
</script>
</body>

8. 操作表单元素属性

表单很多情况,也需要修改属性。比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框。

获取:DOM对象.属性名

设置:DOM对象.属性名=新值

表单.value=’用户名’

表单.type=’password’

获取表单里面的值,是用表单.value

例如:const uname=document.querySelector(‘input’),console.log(uname.value)

注意:innerHTML得不到表单的内容,即不可以写成uname.innerHTML

表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示,如果为true代表添加了该属性,如果是false代表移除了该属性

比如:disabled,checked,selected

9. 操作DOM节点

1. 元素节点,所有的标签,比如body,div,html是根节点

2. 属性节点,所有的属性 比如href

3. 文本节点,所有的文本

节点关系:针对的找亲戚返回的都是对象

获取元素通常使用两种方式

1. 利用DOM提供的方法获取元素

documentgetElementById()

documentgetElementsByTagName()

document.querySelector等

逻辑性不强,繁琐

2. 利用节点层次关系获取元素

利用父子兄节点关系获取元素

以上两种方法都可以获取元素节点,都会常使用,但是节点操作更简单

3. 节点概述

网页中的所有内容都是节点(标签,属性,文本,注释等),在DOM中,节点使用node来表示

一般而言,节点至少拥有nodeType(节点类型), nodeName(节点名称), nodeValue(节点值)这三个基本属性

在实际开发中,节点操作主要操作的是元素节点

4. 节点层级

最常见的是父子兄层级关系

1. 父级节点

node.parentNode

返回的是最近的一个父节点

如果指定的节点没有父节点则返回null

2. 子节点

parentNode.childNodes(标准)

返回值里面包含了所有的子节点,包括元素节点,文本节点

如果只想要获得里面的元素节点,则需要专门处理。(所以我们一般不提倡使用childNodes)

parentNode.children(非标准)

parentNode.children是一个只读属性,返回所有的子元素节点

它只返回子元素节点,其余节点不返回(重点掌握)

parentNode.firstChild

firstChild返回第一个子节点,找不到则返回null(包含所有的节点)

parentNode.lastChild

lastChild返回最后一个子节点,找不到则返回null(包含所有的节点)

//以下有兼容性问题

parentNode.firstElementChild

firstElementChild返回第一个子元素节点,找不到则返回null

parentNode.lastElementChild

lastElementChild返回最后一个子元素节点,找不到则返回null

//实际开发中,我们常常使用parentNode.childern[i],获取返回的所有的子元素节点中的其中一个。

3. 兄弟节点

1. node.nextSibling

nextSibling返回当前元素的下一个兄弟节点,找不到则返回null。(包含所有节点)

2. node.previousSibling

previousSibling返回当前元素上一个兄弟节点,找不到则返回null。(包含所有节点)

//以下有兼容性问题

1. node.nextElementSibling

nextElementSibling返回当前元素下一个兄弟元素节点,找不到则返回null

2. node.previousElementSibling

previousElementSibling返回当前元素上一个兄弟元素节点,找不到则返回null

4. 创建节点

即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点

//创造元素节点方法

document.createElement(‘标签名’)

document.createElement(‘tagName’)

5. 添加节点

将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after伪元素

node.appendChild(child)

node是父级 child是子级

将一个节点添加到父节点指定子节点前面。类似于css里面的before伪元素

node.insertBefore(child,指定元素)

6. 删除节点

在JavaScript原生DOM操作中,要删除元素必须通过父元素删除

语法:父元素.removeChild(要删除的元素)

从DOM中删除一个子节点,返回删除的节点

注意:如不存在父子关系则删除不成功

删除节点和隐藏节点(display:none)有区别的:隐藏节点还是存在的,但是删除,则从html中删除节点。

7. 复制节点(克隆节点)

node.cloneNode()

返回调用该方法的节点的一个副本。也称克隆节点/拷贝节点

如果括号参数为空或者为false,则是浅拷贝,即只克隆节点本身,不复制里面的内容

括号里面的参数为true,深拷贝,则会复制里面的内容

10. 三种动态创建元素的区别

1. document.write();

//直接将内容写入页面的内容流,但是文档流执行完毕,会导致页面全部重绘

2. innerHTML创建多个元素效率更高(不要拼接字符串,采用数组形式拼接)结构稍复杂

3. ceeateElement()创建多个元素效率稍低一点点,但是结构更清晰

4. 事件高级

1. 元素注册事件的两种方式

注册事件(绑定事件),给元素添加事件,称为注册事件或者绑定事件

1. 传统方式:利用on开头的事件(onclick)

<button onclick=”alert(‘hi~’)”></button>
btn.onclick=function(){}

特点:注册事件的唯一性

同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。

2. 方法监听:w3c标准(推荐方式)

1. addEventListener()   (它是一个方法)

IE9之前的IE不支持此方法,可使用attachEvent()代替

特点:同一个元素同一个事件可以注册多个监听器

按注册顺序依次执行

eventTarget.addEventListener(type,listener[,useCapture])

将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,就会执行事件处理函数。

该方法接收三个参数:

type: 事件类型字符串,比如click,mouseover,注意这里不要带on

listener: 事件处理函数,事件发生时,会调用该监听函数

useCapture: 可选参数,是一个布尔值,默认是false。学完DOM事件流后,进一步学习。

2. attachEvent

eventTarget.attachEvent(eventNameWithOn,callback)

将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,指定的回调函数就会被执行。

该方法接收两个参数:

eventNameWithOn: 事件类型字符串,比如onclick, onmouseover (这里要带on)

callback: 事件处理函数,当目标触发事件时回调函数被执行。

2. 删除事件(解绑事件)

1. 传统注册方式:element.οnclick=null;

2. 方法监听注册函数 :eventTarget.removeEventListener(type,listener[,useCapture]);

3. eventTarget.detachEvent(eventNameWithOn,callback);

3. DOM事件流

事件流描述的是从页面中接收事件的顺序。

事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

DOM事件流分为3个阶段

1. 捕获阶段(从大往小)

Document  >>  Element html  >>  Element body  >>  Element div

2. 当前目标阶段

3. 冒泡阶段

Element div  >>  Element body  >>  Element html  >>  Document

1. 事件捕获概念

从DOM的根元素开始去执行对应的事件(从外到里)

事件捕获需要写对应代码才能看到效果

代码:DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

说明:addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)

若传入false代表冒泡阶段触发,默认就是false

若是使用L0事件监听(就是那个onclick),则只有冒泡阶段,没有捕获

2. 事件冒泡概念

当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为冒泡。

简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件(例如都是click)

事件冒泡是默认存在的

L2监听事件(就是那个addEventListener)第三个参数是false,或者默认都是冒泡

3. 阻止冒泡

需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡

前提:阻止事件冒泡需要拿到事件对象

语法:事件对象.stopPropagation()

注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。

4. 解绑事件

on事件方式,直接使用null覆盖就可以实现事件的解绑

语法:

//绑定事件
btn.onclick = function() {
    alert(‘点击了’)
}
//解绑事件
btn.onclick = null

removeEventListener(事件类型,事件处理函数,[获取捕获或者冒泡阶段]) 

// 例如
function fn() {
    alert(‘点击了’)
}
//绑定事件
btn.addEventListener(‘click’,fn)
//解绑事件
btn.removeEventListener(‘click’,fn)
//注意:匿名函数无法被解绑

5. 两种注册事件的区别

1. 传统on注册(L0)

同一个对象,后面注册的事件会覆盖前面注册(同一个事件)

直接使用null覆盖就可以实现事件的解绑

都是冒泡阶段执行

2. 事件监听注册(L2)

后面注册的事件不会覆盖前面注册的事件(同一个事件)

可以通过第三个参数去确定是在冒泡或捕获阶段执行

必须使用removeEventListener(事件类型,事件处理函数,获取捕获或冒泡阶段)

匿名函数无法被解绑

注意:

1. JS代码中只能执行捕获或者冒泡其中的一个阶段

2. onclick和attachEvent只能得到冒泡阶段

3. addEventListener(type,listener[,useCapture])  

第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;

如果是false(不写默认是false),表示在事件冒泡阶段调用事件处理程序。

1. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。

2. 有些事件是没有冒泡的,比如onblur,onfous,onmouseenter,onmouseleave

3. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事情。

4. 事件对象(有兼容性问题)

官方解释:event对象代表事件的状态,比如键盘按键的状态,鼠标的位置,鼠标按钮的状态

事件对象有了事件才会存在,它是系统系统自动创建的,不需要我们传递参数。

事件对象写到侦听函数的小括号里面,当形参来看。

事件对象是事件的一系列相关数据的集合,跟事件相关的(例如,鼠标点击里面就包含了鼠标的相关信息,鼠标坐标等;如果是键盘事件里面就包含的键盘事件的信息 比如判断用户按下了哪个键)

这个事件对象,我们可以自己命名(例如 event,evt,e等等)

使用场景:

可以判断用户按下哪个键,比如按下回车键可以发布新闻

可以判断鼠标点击了哪个元素,从而做相应的操作

5. 事件对象常见属性和方法

事件对象属性方法

说明

e.target

返回触发事件的对象(标准)

e.srcElement

返回触发事件的对象(非标准)

e.type

返回事件的类型(比如click mouseover 不带on)

e.canxelBubble

该属性阻止冒泡(非标准)

e.returnValue

该属性阻止默认事件(默认行为)(非标准) 比如不让链接跳转

e.prewentDefault()

该方法阻止默认事件(默认行为)(标准) 比如 不让链接跳转

e.stopPropagation()

阻止冒泡(标准)

6. e.target和this的区别

e.target返回的是触发事件的对象(元素)

this返回的是绑定事件的对象(元素)

跟this有个非常相似的属性currentTarget  (ie678不认识)

7. 阻止事件冒泡

事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层。

标准写法:利用事件对象里面的stopPropagation()方法

非标准写法:IE6-8利用事件对象canceBubble属性(e.canceBubble= true;)

8. 事件委托(代理,委派)

思考:如果同时给多个元素注册事件,我们怎么做的?for循环注册事件

有没有一种技巧,注册一次事件就能完成以上效果呢?

事件委托是利用事件流的特征解决一些开发需求的知识技巧

优点:减少注册次数,可以提高程序性能

原理:事件委托其实是利用事件冒泡的特点

给父元素注册事件。当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。

实现:事件对象.target.tagName可以获得真正触发事件的元素

9. 常用的鼠标事件

鼠标事件

触发条件

onclick

鼠标点击左键触发

onmouseover

鼠标经过触发

onmouseout

鼠标离开触发

onfocus

获得鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmouseup

鼠标弹起触发

onmousedown

鼠标按下触发

1. 禁止鼠标右键菜单

contextmenu(主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单)

2. 禁止鼠标选中(selectstart 开始选中)

3. 鼠标经过事件的区别

mouseover和mouseout会有冒泡效果

mouseenter和mouseleave没有冒泡效果(推荐)

10. 鼠标事件对象

event对象代表事件的状态,跟事件相关的一系列信息的集合。

现阶段我们主要是使用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent

鼠标事件对象

说明

e.clientX

返回鼠标相对于浏览器窗口可视区的X坐标

e.clientY

返回鼠标相对于浏览器窗口可视区的Y坐标

e.pageX

返回鼠标相对于文档页面的X坐标IE9+支持

e.pageY

返回鼠标相对于文档页面的Y坐标IE9+支持

e.screenX

返回鼠标相对于电脑屏幕的X坐标

e.screenY

返回鼠标相对于电脑屏幕的Y坐标

11. 常用的键盘事件

键盘事件

触发条件

onkeyup

某个键盘按键被松开时触发

onkeydown

某个键盘案件被按下时触发

onkeypress

某个键盘案件被按下时触发(但它不识别功能键 如ctrl shift箭头等)

keyup和keydown事件不区分字母大小写,keypress区分字母大小写。

keydown和keypress在文本框里面的特点:

他们两个事件触发的时候,文字还没有落入文本框中

keyup事件触发的时候。文字已经落入文本框中了

5. BOM

即浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window

BOM由一系列的对象构成,并且每个对象都提供了很多方法和属性

BOM缺乏标准。(JavaScript语法的标准化组织是ECMA,DOM标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分)

1. 对比DOM和BOM

DOM

BOM

文档对象模型

浏览器对象模型

DOM就是把文档当作一个对象来看待

把浏览器当作一个对象来看待

DOM的顶级对象是document

BOM的顶级对象是window

DOM主要学习的是操作元素页面

BOM学习的浏览器窗口交互的一些对象

DOM是W3C规范

BOM是浏览器厂商在各自浏览器上定义的,兼容性差

2. BOM的构成

BOM比DOM更大,它包含DOM

window>document

window>location

window>navigation

window>screen

window>history

window对象是浏览器的顶级对象,它具有双重角色

1. 它是JS访问浏览器窗口的一个接口

2. 它是一个全局对象。定义在全局作用域中的变量,函数都会变成window对象的属性和方法

但是,在调用的时候,可以省略window。

前面学习的对话框都属于window对象方法,如alert(),prompt()等

3. window对象的常见事件

1. 窗口加载事件

为什么要学:有些时候需要等页面资源全面处理完了做一些事情,老代码喜欢把script写在head中,这时候直接找dom元素找不到。

//页面加载事件

window.addEventListener(‘load’,function(){
    //执行的操作
})

window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,CSS文件),就调用的处理函数

有了window.onload,就可以把JS代码写到页面元素的上方。因为onload是等页面内容全部加载完毕,再去执行处理函数

window.onload=function() {}

当初始的HTML文档完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表,图像等完全加载。

监听页面DOM加载完毕:给document添加DOMContentLoaded事件

document.addEventListener(‘DOMContentLoad’,function(){
    //执行操作
})

如果页面的图片很多的话,从用户访问到onload触发可能需要较长的事件,交互效果就不能实现,必然影响用户的体验,此时用DOMContenrLoaded事件比较合适。

2. 调整窗口大小事件

会在窗口尺寸改变的时候触发事件resize

window.οnresize=function(){}

window.addEventListener(“resize”,function() {} );

注意:

1. 只要窗口大小发生像素变化,就会触发这个事件

2. 我们经常利用这个事件完成响应式布局。window.innerWidth当前屏幕的宽度

3. 获取宽高:clientWidth和clientHeight,获取元素的可见部分宽高(不包含边框,margin,滚动条等)

检测屏幕宽度:

window.addEventListener(‘resize’,function() {
    let w=document.documentElement.clientWidth
    console.log(w)
})

4. 获取宽高:offsetWidth和offsetHeight,获取元素的自身宽高,包含元素自身设置的宽高,padding,border

注意:获取的是可视宽高,如果盒子是隐藏的,获取的结果是0。

offsetWidth和offsetHeight 与clientWidth和clientHeight唯一不同的就是后者获取的宽高不包含border。

5. 获取位置:offsetLet和offsetTop注意是只读属性,获取元素距离自己定位父级元素的左,上距离

3. 元素滚动事件

滚动条在滚动的时候持续触发的事件

为什么要学:很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部。

监听整个页面滚动:事件名:scroll

//页面滚动事件
window.addEventListener(‘scroll’,function(){
    //执行的操作
})

给window或document添加scroll事件,监听某个元素的内部滚动直接给某个元素加即可。

页面滚动事件-获取位置:scrollLeft和scrollTop(属性)

获取被卷去的大小获取元素内容往左,往上滚出去看不到的距离,这两个值是可读写的。

4. setTimeout()定时器

JavaScript内置的一个用来让代码延迟执行的函数,叫setTimeout

语法:setTimeout(回调函数,等待的毫秒数)

setTimeout仅仅执行一次,所以可以理解为就是把一段代码延迟执行,平时省略window

清除延时函数:

let timer=setTimeout(回调函数,等待的毫秒数)

clearTimeout(timer)

注意:延时器需要等待,所以后面的代码先执行,每一次调用延时器都会产生一个新的延时器

两种定时器对比:(执行的次数)

延时函数:执行一次

间歇函数:每隔一段时间就执行一次,除非手动清除。

注意:

1. window可以省略

2. 这个调用函数,可以直接写函数,或者写函数名,或者采取字符串‘函数名()’三种形式。

3. 延迟的毫秒数默认是0,如果写,必须是毫秒

setTimeout()这个调用函数我们也称为回调函数(callback)

普通函数是按照代码顺序直接调用。而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。

以前讲的element.οnclick=function() {}或者element.addEventListener(“click”,fn); 里面的函数也是回调函数。

5. 停止setTimeout()定时器

window.clearTimeout(timeoutID)

clearTimeout()方法取消了先前通过调用setTimeout()建立的定时器

注意:

1. window可以省略

2. 里面的参数就是定时器的标识符

6. setInterval()定时器

window.setInterval(回调函数,[间隔的毫秒数]);

setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。

注意:

1. window可以省略

2. 这个调用函数,可以直接写函数,或者写函数名,或者采取字符串‘函数名()’三种形式。

3. 延迟的毫秒数默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数

4. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符

7. this指向问题

一般情况下,this的最终指向的是那个调用它的对象

1. 全局作用域或普通函数中this指向全局对象window(注意定时器里面的this指向window)

2. 方法调用中谁调用this指向谁

3. 构造函数中this指向构造函数的实例

8. JS执行机制

JavaScript语言的一大特点就是单线程(即同一个时间只能做一件事)

单线程意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。

这就会导致(如果JS执行时间过长,就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉)

为了解决这个问题,利用多核CPU的计算能力,HTML5提出了Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS出现了同步和异步

同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的,同步的。

异步:在做一件事时,还可以处理其他事情。

他们的本质区别: 这条流水线上各个流程的执行顺序不同。

同步任务:同步任务都在主线程上执行,形成一个执行栈

异步任务:JS的异步是通过回调函数实现的

一般而言,异步任务有以下三种类型

1. 普通事件,如click,resize等

2. 资源加载,如load,error等

3. 定时器,包括setInterval,setTimeout等

异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)

JS执行机制

1. 先执行执行栈中的同步任务

2. 异步任务(回调函数)放入任务队列中。

3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

8. 事件循环

由于主线程不断的重复获得任务,执行任务;再获取任务,再执行,所以这种机制被称为事件循环(event loop)

9. location对象

window对象给我们提供了一个location属性,用于获取或设置窗体的url,并且可以用于解析URL。(因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象)

URL(统一资源定位符)

URL的一般语法格式:protocol://host[:port]/path/[?query]#fragment

http://www.itcast.cn/index.html?name=andy&age=18#link

href属性获取完整的URL地址,对其赋值时用于地址的跳转

//可以得到当前文件URL地址

console.log(location.href)

//可以通过js方式跳转到目标地址

location.href=’http://www.baidu.com’

//search属性获取地址中携带的参数,符号?后面部分

console.log(location.search)

//hash属性获取地址中的哈希值,符号#后面部分。

console.log(location.hash)

(后期vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如网易云音乐)

reload方法用来刷新当前页面,传入参数true时表示强制刷新

组成

说明

protocal

通信协议 常用的http,ftp,maito等

host

主机(域名)

port

端口号(可选) 如http默认的端口号为80

path

路径(由零或多个’/’符号隔开的字符串),一般用来表示主机上的一个目录或文件地址

query

参数 以键值对的形式出现(通过&符号分隔开)

fragment

片段 #后面内容(常见于链接 锚点)

location对象的属性

location对象属性

返回值

location.href

获取或者设置整个URL

location.host

返回主机(域名)

location.port

返回端口号(如果未写 返回空字符串)

location.pathname

返回路径

location.search

返回参数

location.hash

返回片段 #后面内容(常见于链接 锚点)

location对象的方法

location对象方法

返回值

location.assign()

跟href一样,可以跳转页面(记录历史)(也被称为重定向页面)

location.replace()

替换当前页面,因为不记录历史,所以不能后退页面

location.reload()

重新加载页面,相当于刷新按钮或者F5;如果参数为true 强制刷新ctrl+f5

10. navigator对象

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。

navigator的数据类型是对象,该对象记录了浏览器自身的相关信息

常用属性和方法:

通过userAgent检测浏览器的版本和平台

//检测userAgent(浏览器信息)

!function({
    const userAgent=navigator.userAgent

    //验证是否为Android或iPhone
    const android=userAgent.math(/Android);?[¥s¥/]+([¥d.]+)?/)
    const iPhone=userAgent.math(/(iPhone¥sOS)¥s([¥d_]+)/)

    //如果是Android或iPhone,则跳转至移动站点
    if(android || iphone) {
        location.href=’http://m.itcast.cn’
    })
})

11. history对象

与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

history的数据类型是对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应,如前进,后退,历史记录等

history对象一般在实际开发中比较少用,但是会在一些OA办公系统中见到。

history对象方法

作用

back()

可以后退功能

forward()

前进功能

go(参数)

前进后退功能(参数如果是1 前进一个页面;如果是-1,后退一个页面)

6. 事件监听

事件:是在编程时系统内发生的动作或者发生的事情

比如用户在网页上单击一个按钮

事件监听:就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为绑定事件或者注册事件。

比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等

语法:元素对象.addEventListener(‘事件类型’,要执行的函数)

1. 事件监听三要素

事件源:那个dom元素被事件触发了,要获取dom元素

事件类型:用什么方式触发,比如鼠标点击click,鼠标经过mouseover等

事件调用的函数:要做什么事

语法:

<button>按钮</button>

<script>
    const btn=document.querySelector(‘.btn’)
    //修改元素样式
    btn.addEventListener(‘click’,function(){
        alert(‘点击了~’)
    })
</script>

注意:事件类型要加引号,函数是点击之后再去执行,每次点击都会执行一次。

2. 事件监听版本

DOM L0:事件源.on事件=function(){}

DOM L2:事件源.addEventListener(事件,事件处理函数)

区别:on方式会被覆盖,addEventListener方式可以绑定多次,拥有事件更多特性,推荐使用

7. 事件类型

1. 鼠标事件

鼠标触发:click 鼠标点击,mouseenter 鼠标经过,mouseleave 鼠标离开

2. 焦点事件

表单获得光标:focus 获得焦点,blur 失去焦点

3. 键盘事件

键盘触发:keydown 键盘按下触发,keyup 键盘抬起触发

4. 文本事件

表单输入触发:input 用户输入事件

5. M端事件

移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。

touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。

触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作

触屏touch事件

说明

touchstart

手指触摸到一个DOM元素时触发

touchmove

手指在一个DOM元素上滑动时触发

touchend

手指从一个DOM元素上移开时触发

8. 回调函数

如果将函数A作为参数传递给函数B时,我们称函数A为回调函数

简单理解:当一个函数当做参数来传递给另一个函数的时候,这个函数就是回调函数

常见的使用场景:

function fn () {
    console.log(‘我是回调函数...’)
}

//fn传递给了setInterval,fn就是回调函数
setInterval(fn,1000)

box.addEventListener(‘click’,function(){
    console.log(‘我也是回调函数’)
})

回调函数:把函数当作另外一个函数的参数传递,这个函数就叫回调函数

回调函数本质还是函数,只不过把它当成参数使用

使用匿名函数作为回调函数比较常见

9. 阻止默认行为

我们某些情况下需要阻止默认行为的发生,比如阻止链接的跳转,表单域跳转

语法:e.preventDefault()

例如:

<form action=”http://www.baidu.com”>
    <input type=”submit” value=”提交”>
</form>

<script>
const form=document.querySelector(‘form’)
form.addEventListener(‘click’,function(e) {
    //阻止表单默认提交行为
    e.preventDefault()
})
</script>

三. JavaScript进阶

1. 箭头函数

箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁。

1. 使用场景

箭头函数更适合于那么本来需要匿名函数的地方

// 原始写法
const fn=function() {
    console.log(123)
}

// 箭头函数 基本语法
const fn =() = > {
    console.log(123)
}
fn()

//传参
const fn=(x) => {
    console.log(x)
}
fn(1)

//只有一个形参的时候,可以省略小括号
const fn = x => {
    console.log(x)
}
fn(1)

//只有一行代码的时候,我们可以省略大括号
const fn = x => console.log(x)
fn(1)

//只有一行代码的时候,我们可以省略return
//普通函数
const fn=function(x,y){
    return x+y
}
console.log(fn(1,2))

//箭头函数
const fn=(x,y) => x+y
console.log(fn(1,2))

//加括号的函数体返回对象字面量表达式
const fn1=uname => ({uname:name})
console.log(fn1(‘pink老师’))

2. 箭头函数参数

1. 普通函数有arguments动态参数

2. 箭头函数没有arguments动态参数,但是有剩余参数...args

3. 箭头函数this

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this

2. 函数参数

1. 动态参数

arguments是函数内部内置的伪数组变量。它包含了调用函数时传入的所有实参。

2. 剩余参数

剩余参数允许我们将一个不定数量的参数表示为一个数组。

...是语法符号,置于最末函数形参之前,用于获取多余的实参。

借助...获取的剩余实参,是个真数组

开发中,还是提倡多使用剩余参数。

3. 展开运算符

展开运算符(...),将一个数组进行展开

const arr=[1,5,3,8,2]

console.log(...arr)  //1 5 3 8 2

说明:不会修改原数组

4. 展开运算符or剩余参数

剩余参数:函数参数使用,得到真数组

展开运算符:数组中使用,数组展开

function getSum(...other) {
    //other 得到[1,2,3]
    console.log(other)
}
getSum(1,2,3)

const arr=[1,5,3,8,2]
console.log(...arr)  //1 5 3 8 2

3. 闭包

1. 概念

一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。

简单理解:闭包=内层函数+外层函数的变量

例如:

function outer(){
    const a=1
    function f() {
        console.log(a)
    }
    f ()
}
outer()

2. 闭包作用

封闭数据,提供操作,外部也可以访问函数内部的变量。

闭包的基本格式:

function outer() {
    let i=1
    function fn() {
        console.log(i)
    }
    return fn
}
const fun=outer()
//外层函数使用内部函数的变量
fun()

//简约写法
function outer() {
    let i=1
    return function() {
        console.log(i)
    }
}
const fun=outer()
// 调用函数
fun()  
// 外层函数使用内部函数的变量

3. 闭包应用

1. 封闭数据,实现数据私有,外部也可以访问函数内部的变量。

2. 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。

比如,我们要做个统计函数调用次数,函数调用一次,就++

let count=1
function fn() {
    count++
    console.log(`函数被调用${count}次`)
}
fn() //2
fn() //3

但是,这个count是个全局变量,很容易被修改。所以应该改进为:

function fn() {
    let count=1
    function fun() {
        count++
        console.log(`函数被调用${count}次`)
    }
    return fun
}
const result = fn()
result() //2
result() //3

//这样实现了数据私有,无法直接修改count

4. 变量提升和函数提升

1. 变量提升

允许在变量声明之前即被访问(仅存在于var声明变量)

注意:

1. 变量在未声明即被访问时会报语法错误

2. 变量在var声明之前即被访问,变量的值为undefined

3. let/const声明的变量不存在变量提升

4. 变量提升出现在相同作用域当中

5. 实际开发中推荐先声明再访问变量

<script>
//访问变量 str
console.log(str+’world!’)
//声明变量 str
var str=’hello’
</script>

正因为如此,ES6引入了块级作用域,用let或者const声明变量,让代码写法更加规范和人性化。

2. 函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用。

//调用函数
foo()

//声明函数
function foo() {
    console.log(‘声明之前即被调用...’)
}


//不存在提升现象
bar()  //错误
var bar=function() {
    console.log(‘函数表达式不存在提升现象...’)
}

总结:

1. 函数提升能够使函数的声明调用更灵活

2. 函数表达式不存在提升的现象

3. 函数提升出现在相同作用域当中

5. 垃圾回收机制

垃圾回收机制简称GC

JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收

1. 内存的生命周期

JS环境中分配的内存,一般有如下生命周期:

1. 内存分配:当我们声明变量,函数,对象的时候,系统会自动为他们分配内存

2. 内存使用:即读写内存,也就是使用变量,函数等

3. 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存

说明:全局变量一般不会回收(关闭页面回收),一般情况下局部变量的值,不用了,会被自动回收掉。

2. 内存泄露

程序中分配的内存由于某种原因程序未释放无法释放叫做内存泄露

3. JS垃圾回收机制-算法说明

1. 栈(操作系统):由操作系统自动分配释放函数的参数值,局部变量等,基本数据类型放到栈里面。

2. 堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面。

两种垃圾回收算法:引用计数法和标记清除法

4. 引用计数法

IE采用的引用计数法,定义“内存不再使用”,就是看一个对象是否有指向它的引用,没有引用了就回收对象。

算法:

1. 跟踪记录被引用的次数

2. 如果被引用了一次,那么就记录次数1,多次引用就会累加++

3. 如果减少1个引用就减1--

4. 如果引用次数是0,则释放内存

存在的问题:嵌套引用(循环引用)

如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄露。

5. 标记清除法

现代浏览器已经不再使用引用计数算法了。

现代浏览器通用的大多是基于标记清除算法的某些改进算法,总体思想都是一致的。

核心:

1. 标记清除算法将“不再使用的对象”定义为“无法达到的对象”。

2. 就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。

3. 那些无法从根部出发触及到的对象被标记为不再使用,稍后进行回收

6. 解构赋值

1. 数组解构

原本书写:

const arr=[100,60,80]
const max=arr[0]
const min=arr[1]
const avg=arr[2]

console.lpg(max)
console.log(min)
console.log(avg)

//以上书写,较为麻烦,可通过解构赋值的方法让代码更简洁。

const [max,min,avg]=[100,60,80]

console.log(max)
console.log(min)
console.log(avg)

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。

基本语法:典型应用交互2个变量

注意:js前面必须加分号的情况。

1. 立即执行函数

(function t() {} )();或者;(function t() {} )()

2. 数组解构

//数组开头的,特别是前面有语句的一定要注意加分号

;[b,a]=[a,b]

例如:

let a=1

let b=3;

[b,a]=[a,b]

3. 变量多,单元值少的情况

变量的数量大于单元值数量时,多余的变量将被赋值为undefined

4. 变量少,单元值多的情况

5. 利用剩余参数,解决变量少,单元值多的情况,剩余参数返回的还是一个数组

6. 防止有undefined传递单元值的情况,可以设置默认值:

允许初始化变量的默认值,且只有单元值为undefined时默认值才会生效。

7. 支持多维数组的解构

2. 对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法

1. 基本语法:

1. 赋值运算符=左侧的{}  用于批量声明变量,右侧对象的属性将被赋值给左侧的变量

2. 对象属性的值将被赋值给与属性名相同的变量

3. 注意解构的变量名不要和外面的变量名冲突,否则报错

4. 对象中找不到与变量名一致的属性时变量值为undefined

2. 给新的变量名赋值

可以从一个对象中提取变量并同时修改新的变量名

冒号表示”什么值:赋值给谁”

3. 数组对象解构

7. 数组的一些方法

1. forEach方法(重点)

forEach()方法用于调用数组的每个元素,并将元素传递给回调函数

主要使用场景:遍历数组的每个元素

注意:

1. forEach主要是遍历数组

2. 参数当前数组元素是必须要写的,索引号可选

语法:

被遍历的数组.forEach(function(当前数组元素,当前元素索引号) {

        //函数体

})

// 例如
const arr=[‘pink’, ‘red’, ‘green’]
arr.forEach(function (item,index) {
    console.log(`当前数组元素是:${item}`)
    console.log(`当前数组元素的索引是:${index}`)
})

2. filter()方法

创建了一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

主要使用场景:筛选数组符合条件的元素,并返回筛选之后的新数组

语法:

被遍历的数组.filter(function (currentValue, index) {

        return 筛选条件

})

//例如,筛选数组中大于30的元素
const score = [10, 50, 3, 40, 33]
const re = score.filter (function (item) {
    return item>30
})
console.log(re)  //[50,40,33]

1. filter()筛选数组

2. 返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组

3. 参数:currentValue必须写,index可选

4. 因为返回新数组,所以不会影响原数组。

8. 实例成员和静态成员

1. 实例成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。(即实例属性和实例方法)

说明:

1. 为构造函数传入参数,创建结构相同但值不同的对象

2. 构造函数创建的实例对象彼此独立互不影响

2. 静态成员

构造函数的属性和方法被称为静态成员(即静态属性和静态方法)

说明:

1. 静态成员只能构造函数来访问

2. 静态方法中的this指向构造函数

比如Date.now() Math.PI Math.random()

9. 内置构造函数

在JavaScript中最主要的数据类型有6种:

基本数据类型:字符串,数值,布尔,undefinednull

引用类型:对象

但是,我们发现,例如:

//普通字符串
const str=’andy’
console.log(str.length)  //4

其实,字符串,数值,布尔,等基本类型,也都有专门的构造函数,这些我们称为包装类型。JS中几乎所有的数据都可以基于构成函数创建。

引用类型:Object,Array,RegExp,Date

包装类型:String,Number,Boolean等

1. Object

Object是内置的构造函数,用于创建普通对象。

//通过构造函数创建普通对象

const user = new Object({name:’小明’,age:15})

推荐使用字面量方式声明对象,而不是Object构造函数。

三个常用静态方法(静态方法就是只有构造函数Object可以调用的)

Object.keys   静态方法获取对象中所有属性(键),返回的是一个数组

Object.values   静态方法获取对象中所有属性(值),返回的是一个数组

Object.assign   静态方法常用于对象拷贝,经常用于给对象添加属性

2. Array

Array是内置的构造函数,用于创建数组

const arr= new Array(3,5)

console.log(arr) //[3,5]

创建数组建议使用字面量创建,不用Array构造函数创建

1. 数组常见实例方法

方法

作用

说明

forEach

遍历数组

不返回数组,经常用于查找遍历数组元素

filter

过滤数组

返回新数组,返回的是筛选满足条件的数组元素

map

迭代数组

返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组

reduce

累计器

返回累计处理的结果,经常用于求和等

reduce基本语法:

arr.reduce(function(){},起始值)

arr.reduce(function(上一次值,当前值){},初始值)

参数:

1. 如果没有起始值,则上一次值以数组的第一个数组元素的值

2. 每一次循环,把返回值给做为下一次循环的上一次值

3. 如果有起始值,则起始值作为上一次值

2. 数组常见方法-其他方法

join

数组元素拼接为字符串

返回字符串(重点)

find

查找元素

返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回undefined(重点)

every

检测数组所有元素是否都符合指定条件,如果所有元素都通过检验返回true,否则返回false(重点)

some

检测数组中的元素是否满足条件,如果数组中有元素满足条件返回true,否则返回false

concat

合并两个数组,返回生成新数组

sort

对原数组单元值排序

splice

删除或替换原数组单元

reverse

反转数组

findIndex

查找元素的索引值

3. String

JavaScript中的字符串,数值,布尔具有对象的使用特征,如具有属性和方法。

之所以具有对象特征的原因是:字符串,数值,布尔类型数据是JavaScript底层使用Object构造函数“包装”来的,被称为包装类型。

实例属性:length: 用来获取字符串的长度(重点)

常见实例方法:

split(‘分隔符’)

用来将字符串拆分成数值

substring(需要截取的第一个字符的索引[,结束的索引号])

用于字符串截取

startsWith(检测字符串[,检测位置索引号])

检测是否以某字符开头

includes(搜索的字符串[,检测位置索引号]

判断一个字符串是否包含在另一个字符串中,根据情况返回truefalse

toUpperCase

用于将字母转换成大写

toLowerCase

用于将字母转换成小写

indexOf

检测是否包含某字符

endsWith

检测是否以某字符结尾

replace

用于替换字符串,支持正则匹配

match

用于查找字符串,支持正则匹配

4. Number

Number是内置的构造函数,用于创建数值

常用方法:toFixed()设置保留小数位的长度

例如:

//数值类型
const price=12.345

//保留两位小数,四舍五入
console.log(price.toFixed(2))  //12.35

10. 编程思想

1. 面向过程编程

面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。(蛋炒饭)

也就是:按照我们分析好了的步骤,按照步骤解决问题。

2. 面向对象编程(OOP)

面向对象:是把事物分解成一个个对象,然后由对象之间分工与合作。(盖浇饭)

也就是:以对象功能来划分问题,而不是步骤。

在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。

面向对象编程具有灵活性,代码可复用,容易维护和开发的优点,更适合多人合作的大型软件项目。

3. 面向对象的特性

封装性,继承性,多态性

面向过程编程

面向对象编程

优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程

优点:易维护,易复用,易扩展,由于面向对象有封装,继承,多态性的特性,可以设计出低耦合的系统,使系统更加灵活,更加易于维护

缺点:没有面向对象易维护,易复用,易扩展

缺点:性能比面向过程低

4. 构造函数体现封装

封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现封装。

同样的变量和函数组合到了一起并能通过this实现数据的共享,所不同的是借助构造函数创建出来的实例对象是彼此不影响的。

总结:

1. 构造函数体现了面向对象的封装特性

2. 构造函数实例创建的对象彼此独立,互不影响。

11. 原型

1. 用原型对象实现方法共享

1. 构造函数通过原型分配的函数是所有对象所共享的

2. JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象。

3. 这个对象可以挂载函数,对象实例化不会多次创建原型函数,节约内存。

4. 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

5. 构造函数和原型对象中的this都指向实例化对象。

2. 原型this指向

构造函数和原型对象中的this都指向实例化的对象

3. 原型继承

继承是面向对象编程的另一个特征,通过继承进一步提高代码封装的程度,JavaScript中大多是借助原型对象实现继承的特性。

需求:男人和女人不要使用同一个对象,但是不同对象里面包含相同的属性和方法

答案:构造函数

new每次都会创建一个新的对象

function Star() {
    this.age=18
    this.say=function() {}
}
const ldh=new Star()
const zxy=new Star()
console.log(ldh)
console.log(zxy)
console.log(ldh===zxy)   //false 每个实例对象都不一样

4. 原型链

基于原型对象的继承,使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链。

5. 原型链——查找规则

1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

2. 如果没有就查找它的原型(也就是__proto__指向的prototype原型对象)

3. 如果还没有,就查找原型对象的原型(Object的原型对象)

4. 依此类推,一直找到Object为止(null)

5. __proto__对象原型的意义就在于为对象成员查找机制提供一个方向(路线)

6. 可以使用instanceof运算符用于检测构造函数的 e属性是否出现在某个实例对象的原型链上

6. constructor属性

每个原型对象里面都有个constructor属性(constrictor构造函数)

作用:该属性指向该原型对象的构造函数

构造函数可以创建实例对象,

构造函数还有一个原型对象(一些公共的属性或者方法放到这个原型对象身上),

那为什么,实例对象可以访问原型对象里面的属性和方法呢?

实例对象都会有一个属性__proto__,指向构造函数的prototype原型对象

之所以我们的实例对象可以使用构造函数的prototype原型对象的属性和方法,

就是因为实例对象有__proto__原型的存在。

注意:

1. __proto__是JS非标准属性

2. [[prototype]]和__proto__意义相同

3. 用来表明当前实例对象指向哪个原型对象prototype

4. __proto__对象原型里面也有一个constructor属性,指向创建该实例对象的构造函数

12. this指向

1. 普通函数

普通函数的调用方式决定了this的值,即【谁调用this的值指向谁】

普通函数没有明确调用者时,this值为window

严格模式下没有调用者时,this的值为undefined

2. 箭头函数

箭头函数中的this与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在this

1. 箭头函数会默认帮我们绑定外层this的值,所以在箭头函数中this的值和外层的this是一样的。

2. 箭头函数中的this引用的就是最近作用域中的this

3. 向外层作用域中,一层一层查找this,直到有this的定义

注意情况1:

在开发中,使用箭头函数前需要考虑函数中this的值,事件回调函数使用箭头函数时,this为全局的window

因此,DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数。

注意情况2:

同样由于箭头函数this的原因,基于原型的面向对象也不推荐采用箭头函数

总结:

1. 函数内不存在this,沿用上一级的

2. 不适用:构造函数,原型函数,dom事件函数等等不适用

3. 适用:需要使用上层this的地方

4. 使用争取的话,它会在很多地方带来方便

3. 改变this指向

JavaScript中还允许指定函数中this的指向,有3个方法可以动态指定普通函数中this的指向。

call()

apply()

bind()

1. call()(了解)

使用call方法调用函数,同时指定被调用函数中this的值

语法:fun.call(thisArg, arg1, arg2,...)

thisArg:在fun函数运行时指定的this值,arg1, arg2:传递的其他参数

返回值就是函数的返回值,因为它就是调用函数

2. apply()(理解)

使用apply方法调用函数,同时指定被调用函数中this的值

语法:fun.apply(thisArg, [argsArray])

thisArg:在fun函数运行时指定的this值,argsArray:传递的值,必须包含在数组里面

返回值就是函数的返回值,因为它就是调用函数

因此apply主要跟数组有关系,比如使用Math.max()求数组的最大值

3. bind()(重点)

bind()方法不会调用函数,但是能改变函数内部this指向

语法:fun.bind(thisArg, arg1,arg2,...)

thisArg:在fun函数运行时指定的this值,arg1,arg2:传递的其他参数

返回“由指定的this值和初始化参数改造的”原函数拷贝(新函数)

因此当我们只是向改变this指向,并且不想调用这个函数的时候,可以使用bind,比如改变定时器内部的this指向

4. call  apply  bind总结

相同点:都可以改变函数内部的this指向

区别点:

call和apply会调用函数,并且改变函数内部this指向

call和apply传递的参数不一样,call传递参数arg1,arg2...形式,apply必须数组形式[arg]

bind不会调用函数,可以改变函数内部this指向

5. 主要应用场景

call调用函数并且可以传递参数

apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值

bind不调用函数,但是还是想改变this指向,比如改变定时器内部的this指向。

13. 深浅拷贝

浅拷贝和深拷贝只针对引用类型

常见方法:

1. 拷贝对象:Object.assgin() /展开运算符{...obj}拷贝对象

2. 拷贝数组:Array.prototype.concat()或者[...arr]

如果是简单数据类型拷贝值,引用数据类型拷贝的是地址

(简单理解,如果是单词对象没问题,如果有多层就有问题)

1. 直接赋值与浅拷贝的区别

直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址。

浅拷贝如果只是一层对象,不互相影响,如果出现多层对象拷贝还是会相互影响。

2. 浅拷贝理解

浅拷贝:拷贝的是地址

拷贝对象之后,里面的属性值是简单数据类型直接拷贝值

如果属性值是应用数据类型则拷贝的是地址。

3. 深拷贝

拷贝的是对象,不是地址

常见方法:

1. 通过递归实现深拷贝

2. lodash/cloneDeep

3. 通过JSON.stringify()实现

4. 函数递归

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。

简单理解:函数内部自己调用自己,这个函数就是递归函数。

递归函数的作用和循环效果类似。

由于递归很容易发生“栈溢出”错误,所以必须要加退出条件return

14. 防抖和节流

1. 防抖

单位之间内,频繁触发事件,只执行最后一次

使用场景:搜索框搜索输入。只需用户最后一次输入完,再发送请求。手机号,邮箱验证输入检测。

2. 防抖实现方式

1. lodash提供的防抖来处理

2. 手写一个防抖函数来处理

3. 防抖核心思路

防抖的核心就是利用定时器(setTimeout)来实现

1. 声明一个定时器变量

2. 当鼠标每次滑动都先判断是否有定时器,如果有定时器先清除以前的定时器

3. 如果没有定时器则开启定时器,记得存到变量里面

4. 在定时器里面调用要执行的函数

4. 节流

单位时间内,频繁触发事件,只执行一次

使用场景:高频事件:鼠标移动mousemove,页面尺寸缩放resize,滚动条滚动scroll等等

需求:鼠标在盒子上移动,不管移动多少次,每隔500ms才+1

5. 核心思路

节流的核心就是利用setTimeout实现

1. 声明一个定时器变量

2. 当鼠标每次滑动都先判断是否有定时器了,如果有定时器则不开启新定时器

3. 如果没有定时器则开启定时器,记得存到变量里面

4. 定时器里面调用执行的函数

5. 定时器里面要把定时器清空

15. 异常处理

throw抛异常

try/catch捕获异常

debugger

1. throw抛异常

异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行。

总结:

1. throw抛出异常信息,程序也会终止执行(throw直接中端程序,不需要写return)

2. throw后面跟的是错误提示信息

3. Error对象配合throw使用,能够设置更详细的错误信息

2. try/catch捕获错误信息

我们可以通过try/catch捕获错误信息(浏览器提供的错误信息),try试试,catch拦住,finally最后。

总结:

1. try...catch用于捕获错误信息

2. 将预估可能发生错误的代码写在try代码段中

3. 如果try代码段中出现错误后,会执行catch代码段,并截获到错误信息

4. finally不管是否有错误,都会执行

怎么调用错误信息?利用catch的参数

16. 日期对象

用来表示时间的对象

作用:可以得到当前系统时间

在代码中,发现了new关键字时,一般将这个操作称为实例化

1. 创建一个实例对象并获取时间

// 获得当前时间:
const date= new Date()

// 获得指定时间:
const date= new Date(‘2008-8-8’)
console.log(date)

2. 日期对象方法

使用场景:因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式。

方法

作用

说明

getFullYear()

获得年份

获得四位年份

getMonth()

获得月份

取值为0~11

getDate()

获得月份中的每一天

不同月份取值也不相同

getDay()

获得星期

取值为0-6(星期天是0)

getHours()

获得小时

取值为0-23

getMinutes()

获得分钟

取值为0-59

getSeconds()

获得秒

取值为0-59

date.toLocaleString()    //2022/4/1 09:41:21

date.toLocaleDateString()    //  2022/4/1

data.toLocaleTimeString()    //  09:41:21

17. 时间戳

使用场景:如果计算倒计时效果,前面方法无法直接计算,需要借助时间戳完成

1. 什么是时间戳

是指1970年01月01日00时00分--秒起至现在的毫秒数,它是一种特殊的计量时间的方式。

算法:将来的时间戳-现在的时间戳=剩余时间毫秒数

剩余时间毫秒数转换为剩余时间的年月日时分秒 就是倒计时的时间

比如:将来的时间戳 2000ms-现在时间戳 1000ms =1000ms

1000ms转换为就是0小时0分1秒

2. 三种获取时间戳的方式

1. 使用getTime()方法

const date=new Date()

console.log(date.getTime())

2. 简写 +new Date()

console.log(+new Date())

无需实例化

3. 使用Date.now()

console.log(Date.now())

无需实例化,但是只能得到当前的时间戳,前面两种可以返回指定时间的时间戳。

18. 元字符

普通字符:

大多数字符仅能描述它们本身,这些字符称作普通字符(例如所有的字母和数字)

也就是说,普通字符只能够匹配字符串中与它们相同的字符。

元字符(特殊字符):是一些具有特殊含义的字符,极大的提高了灵活性和强大的匹配功能。

比如:规定用户只能输入英文26个英文字母,普通字符的话abcdefghijk...

但是换成元字符写法:[a-z]

参考文档:MDN,正则测试工具:在线正则表达式测试

1. 元字符分类

1. 边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)

2. 量词(表示重复次数)

3. 字符类(比如\d 表示0-9)

2. 边界符

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

边界符

说明

^

表示匹配行首的文本(以谁开始)

$

表示匹配行尾的文本(以谁结束)

注意:如果^和$在一起,表示必须是精确匹配。

2. 量词

量词用来设定某个模式出现的次数

量词

说明

*

重复0次或更多次

+

重复1次或更多次

?

重复0次或1次

{n}

重复n次

{n,}

重复n次或更多次

{n,m}

重复n到m次

3. 字符类

1. []匹配字符集合

后面的字符串只要包含abc中任意一个字符,都返回true

2. []里面加上-连字符

使用连字符-表示一个范围

比如:

[a-z]表示a到z  26个英文字母都可以

[a-zA-Z]表示大小写都可以

[0-9]表示0-9的数字都可以

认识下腾讯QQ号:^[1-9][0-9]{4,}$ (腾讯QQ号从10000开始)

3. []里面加上^取反符号

比如:[^a-z]匹配除了小写字母以外的字符

注意要写到中括号里面

4. .匹配除换行符之外的任何单个字符

5. 预定义:指的是某些常见模式的简写方式

预定类

说明

\d

匹配0-9之间任一数字,相当于[0-9]

\D

匹配所有0-9以外的字符,相当于[^0-9]

\w

匹配任意的字母,数字和下划线,相当于[A-Za-z0-9]

\W

除所有字母,数字和下划线以外的字符,相当于[^A-Za-z0-9]

\s

匹配空格(包括换行符,制表符,空格等),相当于[\t\r\n\v\f]

\S

匹配非空格字符串,相当于[^\t\r\n\v\f]

日期格式:^\d{4}-\d{1,2}-\d{1,2}

19. 正则表达式

是用于匹配字符串中字符组合的模式。

在JavaScript中,正则表达式也是对象,通常用来查找,替换那些符合正则表达式的文本,许多语言都支持正则表达式。

正则表达式在javaScript中的使用场景:

匹配:例如表单验证(用户名表单只能输入英文字母,数字或者下划线,昵称输入框中可以输入中文)

替换:例如过滤掉页面内容中的一些敏感词。

提取:从字符串中获取我们想要的特定部分。

javaScript中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:

1. 定义正则表达式语法

const 变量名=/表达式/

其中/  /是正则表达式字面量

比如:const reg=/前端/

2. 匹配符合规则的字符串

test()方法:用来查看正则表达式与指定的字符串是否匹配

语法:regObj.test(被检测的字符串)

exec()方法:在一个指定字符串中执行一个搜索匹配

语法:regObj.exec(被检测字符串)

3. 判断

如果正则表达式与指定的字符串匹配,返回true,否则false

20. 修饰符

修饰符约束正则执行的某些细节行为。如:是否区分大小写,是否支持多行匹配。

语法:/表达式/修饰符

i是单词ignore的缩写,正则匹配时字母不区分大小写

g是单词global的缩写,匹配所有满足正则表达式的结果

console.log(/a/i.test(‘a’))  //true

console.log(/a/i.test(‘A’))  //true

                                         

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值