JavaScript是什么
- 是一种运行在客户端(浏览器)的编程语言,实现人机交互效果
2. 作用(做什么?)
- 网页特效 (监听用户的一些行为让网页作出对应的反馈)
- 表单验证 (针对表单数据的合法性进行判断)
- 数据交互 (获取后台的数据, 渲染到前端)
- 服务端编程 (node.js)
3. JavaScript的组成
ECMAScript:
- 规定了js基础语法核心知识。
- 比如:变量、分支语句、循环语句、对象等等
Web APIs :
- DOM 操作文档,比如对页面元素进行移动、大小、添加删除等操作
- BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等
如何向页面添加 JavaScript
-
行内样式表
-
代码写在标签内部
-
-
COPY<body> <button onClick="alert('这是一个内嵌样式的javascript')" > </button> </body>
-
-
内部样式表
- 直接写在html文件里,用script标签包住
COPY<body> <script language="text"> alert('hello word'); document.write('hello word'); console.log('hello word'); </script> </body>
注意:我们将
JavaScript 注释
单行注释
- 符号://
- 作用://右边这一行的代码会被忽略
- 快捷键:ctrl + /
多行注释
- 符号:/ /
- 作用:在/ 和 / 之间的所有内容都会被忽略
- 快捷键:shift + alt + A
- 直接写在html文件里,用script标签包住
-
JavaScript 结束符
- 结束符
- 代表语句结束
- 英文分号 ;
- 可写可不写(现在不写结束符的程序员越来越多)
- 换行符(回车)会被识别成结束符 ,所以一个完整的语句,不要手动换行
- 因此在实际开发中有许多人主张书写 JavaScript 代码时省略结束符
- 但为了风格统一,要写结束符就每句都写,要么每句都不写(按照团队要求.)
-
常见 JavaScript 输入输出语法
- 输出语法:
document.write('要输出的内容')
alert()
console.log()
- 输入语句
prompt('请输入你的名字')
- 显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字
-
变量的基本使用
-
声明变量
- 语法:
let 变量名(也叫标识符)
- 声明变量有两部分构成:声明关键字、变量名(标识)
- let 即关键字 (let: 允许、许可、让、要),所谓关键字是系统提供的专门用来声明(定义)变量的词语
- 语法:
-
变量的本质
- 内存:计算机中存储数据的地方,相当于一个空间
- 变量:是程序在内存中申请的一块用来存放数据的小空间
-
变量命名规则与规范
- 规则:
- 不能用关键字:关键字:有特殊含义的字符,JavaScript 内置的一些英语词汇。例如:let、var、if、for等
- 只能用下划线、字母、数字、$组成,且数字不能开头
- 字母严格区分大小写,如 Age 和 age 是不同的变量
- 规范:
- 起名要有意义
- 遵守小驼峰命名法:第一个单词首字母小写,后面每个单词首字母大写。例:userName
-
数据类型
JS 数据类型整体分为两大类
-
基本数据类型
- number 数字型
- 即我们数学中学习到的数字,可以是整数、小数、正数、负数。
注意:JS 是弱数据类型,变量到底属于那种类型,只有赋值之后,我们才能确认
- 即我们数学中学习到的数字,可以是整数、小数、正数、负数。
-
string 字符串型
-
通过单引号( '') 、双引号( "")或反引号( ` )包裹的数据都叫字符串,单引号和双引号没有本质上的区别,
推荐使用单引号 -
注意:
- 无论单引号或是双引号必须成对使用
- 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)
- 必要时可以使用转义符 \,输出单引号或双引号
-
字符串拼接
- 作用:拼接字符串和变量
- 符号:\
\
在英文输入模式下按键盘的tab键上方那个键(1左边那个键)内容拼接变量时,用 ${} 包住变量
COPYdocument.write(
大家好。我叫${name}
);
-
- boolean 布尔型
- 表示肯定或否定时在计算机中对应的是布尔类型数据。
- 它有两个固定的值 true 和 false,表示肯定的数据用 true(真),表示否定的数据用 false(假)。
- undefined 未定义型
- 未定义是比较特殊的类型,只有一个值 undefined。
- 只声明变量,不赋值的情况下,变量的默认值为 undefined,一般很少【直接】为某个变量赋值为
undefined。
- null 空类型
- null 表示 值为 空
- null 和 undefined 区别:1. undefined 表示没有赋值,2. null 表示赋值了,但是内容为空
- number 数字型
- 引用数据类型
- object 对象
- function 函数
- array 数组
-
检测数据类型
- 通过 typeof 关键字检测数据类型
console.log(typeof name)
-
类型转换
-
隐式转换
-
某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。
-
规则:
-
+ 号两边只要有一个是字符串,都会把另外一个转成字符串
-
除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
-
缺点:转换类型不明确,靠经验才能总结
-
小技巧:+号作为正号解析可以转换成Number
-
-
显式转换
-
编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。
为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。 -
概念: 自己写代码告诉系统该转成什么类型
-
转换为数字型
-
Number(数据)
-
转成数字类型
-
如果字符串内容里有非数字,转换失败时结果为 NaN(Not a Number)即不是一个数字
-
NaN也是number类型的数据,代表非数字
-
parseInt(数据)
-
只保留整数
-
parseFloat(数据)
-
可以保留小数
-
-
转换为字符型:
- String(数据)
- 变量.toString(进制)
-
-
流程控制
算术运算符
数学运算符也叫算术运算符,主要包括加、减、乘、除、取余(求模)。
- +:求和
- -:求差
- *:求积
- /:求商
- %:取模(取余数)
- 开发中经常作为某个数字是否被整除
-
优先级顺序
- 乘、除、取余优先级相同
- 加、减优先级相同
- 乘、除、取余优先级大于加、减
- 使用 () 可以提升优先级
- 总结: 先乘除后加减,有括号先算括号里面的~~~
-
赋值运算符
-
赋值运算符:对变量进行赋值的运算符
-
已经学过的赋值运算符:= 将等号右边的值赋予给左边, 要求左边必须是一个容器
-
其他赋值运算符:
-
+= 、-= 、*= 、/= 、%
-
使用这些运算符可以在对变量赋值时进行快速操作
-
-
一元运算符
众多的 JavaScript 的运算符可以根据所需表达式的个数,分为一元运算符、二元运算符、三元运算符
- 二元运算符:例:
let num = 10+20
- 一元运算符:例:
let num = ++num
- 自增:符号:++,作用:让变量的值 +1
- 自减:符号:--,作用:让变量的值 -1
- 经常用于计数来使用。 比如进行10次操作,用它来计算进行了多少次
-
比较运算符
- 作用:比较两个数据大小、是否相等
- 比较运算符
- > : 左边是否大于右边
- \<: 左边是否小于右边
- >=: 左边是否大于或等于右边
- \<=: 左边是否小于或等于右边
- ==: 左右两边是否相等
- ===: 左右两边是否类型和值都相等
- !==: 左右两边是否不全等
- 比较结果为boolean类型,即只会得到true或false
- 字符串比较,是比较的字符对应的ASCII码
- NaN不等于任何值,包括它本身
- 尽量不要比较小数,因为小数有精度问题
- 不同类型之间比较会发生隐式转换
- 最终把数据隐式转换转成number类型再比较
- 所以开发中,如果进行准确的比较我们更喜欢 === 或者 !==
-
逻辑运算符
-
逻辑运算符: 符号 名称 日常读法 特点 口诀 && 逻辑与 并且 符号两边都为true
结果才为true一假则假 || 逻辑或 或者 符号两边有一个
true就为true一真则真 ! 逻辑非 取反 true变为false
false变为true真变假,假便真 逻辑运算符里的短路
- 短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行
-
符号 短路条件 && 左边为false就短路 || 左边为true就短路 - 原因:通过左边能得到整个式子的结果,因此没必要再判断右边
- 运算结果:无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值
-
运算符优先级
目标:掌握运算符优先级,能判断运算符执行的顺序 优先级 运算符 顺序 1 小括号 ( ) 2 一元运算符 ++、--、! 3 算数运算符 先*、/、%后加减 4 关系运算符 >、>=、<、 <= 5 相等运算符 ==、!=、===、!== 6 逻辑运算符 先&& 后 |\ 7 赋值运算符 = 8 逗号运算符 , - 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
-
分支语句
- If分支语句
- 单分支
if(){}
- 双分支
if(){}else{}
- 多分支
if(){}else if(){}esle{}
- 单分支
- 三元运算符
- 符号:? 与 : 配合使用
条件?满足条件执行的代码:'不满足条件执行的代码'
- switch 语句
- switch case语句一般用于等值判断,不适合于区间判断
- switch case一般需要配合break关键字使用 没有break会造成case穿透
-
switch(数据){ case 值1: 代码1; break; caes 值1: 代码2 break; default: 代码n break; }
COPY
循环结构
- while循环
- 循环:重复执行某段代码, 而 while : 在…. 期间
- 跟if语句很像,都要满足小括号里的条件为true才会进入执行代码
- while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,若满足又执行大括号里的代码,然后再回到小括号判断条件,直到括号内条件不满足,即跳出
- while 循环注意事项
- 变量起始值
- 终止条件(没有终止条件,循环会一直执行,造成死循环)
- 变量变化量(用自增或者自减)
COPYwhile(循环条件){ 要重负执行的代码(循环体); }
循环退出
- 循环结束:
- continue:结束本次循环,继续下次循环
- break:跳出所在的循环
for循环语法
- 也是重复执行代码
- 好处:把声明起始值、循环条件、变化值写到一起,让人一目了然
COPYfor(声明记录循环次数的变量;循环条件;变化值){ 循环体 }
循环结束:
continue:结束本次循环,继续下次循环
break:跳出所在的循环 -
数组
数组是什么
- 数组(Array)是一种可以按顺序保存数据的数据类型
- 声明语法:
let 数组名=[数据1,数据2,数据3,....,数据n]
- 数组是按顺序保存,所以每个数据都有自己的编号
- 计算机中的编号从0开始
- 在数组中,数据的编号也叫索引或下标
- 数组可以存储任意类型的数据
- 取值语法:
数组名[下标]
- 通过下标取数据
- 取出来是什么类型的,就根据这种类型特点来访问
- 数组的一些术语
- 元素:数组中保存的每个数据都叫数组元素
- 下标:数组中数据的编号
- 长度:数组中数据的个数,通过数组的length属性获得
-
操作数组
数组本质是数据集合, 操作数据无非就是 增 删 改 查 语法:
-
查询数组数据:
数组[下标]
-
修改数组数据:
数组[下标] = 新值
-
数组添加新的数据
- arr.push(新增的内容) 最后的位置添加一条或者多条数据
- 数组.push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度 (重点)
语法: - arr.unshift(新增的内容) 在数组的开头添加数据
- arr.unshift(新增的内容) 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度
-
删除数组中数据
- arr.pop()
- 数组. pop() 方法从数组中删除最后一个元素,并返回该元素的值
- arr.shift()
- 数组. shift() 方法从数组中删除第一个元素,并返回该元素的值
- arr.splice(操作的下标,删除的个数
- 数组. splice(start,deleteCount) 方法 删除指定元素
- start 起始位置:指定修改的开始位置(从0计数)
- deleteCount:表示要移除的数组元素的个数,可选的。 如果省略则默认从指定的起始位置删除到最后
-
函数
- 函数:function,是被设计为执行特定任务的代码块
- 说明:函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势
是有利于精简代码方便复用。 -
函数名命名规范
- 和变量命名基本一致
- 尽量小驼峰式命名法
- 尽量小驼峰式命名法
- 命名建议:常用动词约定
-
有参数的函数声明和调用
参数列表
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个数据用逗号隔开
- 调用函数时,需要传入几个数据就写几个,用逗号隔开
-
形参和实参
- 形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
- 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
- 形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
- 开发中尽量保持形参和实参个数一致
- 我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参
-
函数返回值
-
用return返回数据
- 当函数需要返回数据出去时,用return关键字
-
细节:
- 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
- 函数内部只能出现 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写
- return会立即结束当前函数
- 函数可以没有 return,这种情况函数默认返回值为 undefined
-
作用域
- 作用域概述
- 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这
个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
- 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这
- 全局作用域:作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js文件
- 局部作用域:作用于函数内的代码环境,就是局部作用域。因为跟函数有关系,所以也称为函数作用域。
- 块级作用域:块作用域由 { } 包括,if语句和for语句里面的{ }等
-
变量的作用域
变量有一个坑, 特殊情况:如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐,但是有一种情况,函数内部的形参可以看做是局部变量。
变量访问原则-作用域链
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访
问,就称作作用域链 -
匿名函数
函数可以分为:
- 具名函数:
声明:function fn() {} 调用:fn()
- 匿名函数:
function() {}
- 将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
- 其中函数的形参和实参使用跟具名函数一致。
-
立即执行函数
-
使用场景: 避免全局变量之间的污染
COPY// 方式1 (function(){console.log(11)})(); // 方式2 (function(){console.log(11)}()); //注意,多个立即执行函数之间要用;隔开,不然会报错
对象
对象是什么
-
对象(object):JavaScript里的一种数据类型
-
可以理解为是一种无序的数据集合
-
对象声明语法:
let 对象名={}
-
对象有属性和方法组成
- 属性:信息或叫特征(名词)。 比如 手机尺寸、颜色、重量等...
- 方法:功能或叫行为(动词)。 比如 手机打电话、发短信、玩游戏…
- 属性:
- 数据描述性的信息称为属性,如人的姓名、身高、年龄、性别等,一般是名词性的。
- 属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
- 多个属性之间使用英文 , 分隔
- 属性就是依附在对象上的变量(外面是变量,对象内是属性)
- 属性名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
COPYlet person = { uname:'andy', age:18, sex:'男' } //属性访问 person.uname
- 对象中的方法:数据行为性的信息称为方法,如跑步、唱歌等,一般是动词性的,其本质是函数。
- 方法是由方法名和函数两部分构成,它们之间使用 : 分隔
- 多个属性之间使用英文 , 分隔
- 方法是依附在对象中的函数
- 方法名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
COPYlet person = { uname:'andy', sayHi:function(){ document.write('~~') } } //属性访问 person.uname
操作对象
对象本质是无序的数据集合, 操作数据无非就是 增 删 改 查 语法:
- 查:查询对象:对象.属性 或者 对象[‘属性’],对象.方法()
- 增:对象添加新的数据:对象名.新属性名 = 新值
- 改:重新赋值 对象.属性 = 值,对象.方法 = function() {}
- 删:删除对象中属性 delete 对象名.属性名
- 遍历对象
- 对象没有像数组一样的length属性,所以无法确定长度
- 对象里面是无序的键值对, 没有规律. 不像数组里面有规律的下标
COPYlet obj = { uname:'andy', age:18, sex:'男' } //遍历对象 for(let k in obj){ console.log(k)//打印属性名 console.log(obj[k])//打印属性值 } // 一般不用这种方式遍历数组、主要是用来遍历对象 //一定记住: k 是获得对象的属性名, 对象名[k] 是获得 属性值
#### 内置对象Math - Math对象是JavaScript提供的一个“数学高手”对象 - 提供了一系列做数学运算的方法 - 方法有: - random:生成0-1之间的随机数(包含0不包括1) - ceil:向上取整 - floor:向下取整 - max:找最大数 - min:找最小数 - pow:幂运算 - abs:绝对值
-
生成任意范围随机数
如何生成0-10的随机数呢?
Math.floor(Math.random() * (10 + 1)) //如何生成5-10的随机数? Math.floor(Math.random() * (5 + 1)) + 5 //如何生成N-M之间的随机数 Math.floor(Math.random() * (M - N + 1)) + N
COPY
基本数据类型和引用数据类型的存储方式
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型string ,number,boolean,undefined,null
- 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
-
堆栈空间分配区别
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈,简单数据类型存放到栈里面;
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。引用数据类型存放到堆里面简单类型的内存分配
- 值类型(简单数据类型): string ,number,boolean,undefined,null
- 值类型变量的数据直接存放在变量(栈空间)中
-
复杂类型的内存分配
- 引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
- 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
-
Web API 基本认知
作用和分类
- 作用: 就是使用 JS 去操作 html 和浏览器
- 分类:DOM (文档对象模型)、BOM(浏览器对象模型)
-
什么是DOM
- DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API
- 白话文:DOM是浏览器提供的一套专门用来 操作网页内容 的功能
- DOM作用
- 开发网页内容特效和实现用户交互
-
DOM树
- DOM树是什么
- 将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
- 描述网页内容关系的名词
- 作用:文档树直观的体现了标签与标签之间的关系
-
DOM对象(重要)
-
DOM对象:浏览器根据html标签生成的 JS对象
- 所有的标签属性都可以在这个对象上面找到
- 修改这个对象的属性会自动映射到标签身上
-
DOM的核心思想
把网页内容当做对象来处理
-
document 对象
-
是 DOM 里提供的一个对象
-
所以它提供的属性和方法都是用来访问和操作网页内容的
-
例:document.write()
-
网页所有内容都在document里面
-
-
获取DOM对象
-
选择匹配的第一个元素
-
语法:
document.querySelector('选择器')
- 参数:包含一个或多个有效的各类选择器 字符串
- 返回值:CSS选择器匹配的第一个元素,一个 HTMLElement对象。如果没有匹配到,则返回null。
-
选择匹配的多个元素
- 语法:
document.querySelectorAll('选择器')
- 参数:包含一个或多个有效的选择器 字符串
- 返回值:
CSS选择器匹配的NodeList 对象集合
- 语法:
-
根据CSS选择器来获取DOM元素 (重点)
document.querySelectorAll('选择器')
- 得到的是一个伪数组:
- 有长度有索引号的数组
- 但是没有 pop() push() 等数组方法
-
想要得到里面的每一个对象,则需要遍历(for)的方式获得。注意:哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已
设置/修改DOM元素内容
DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象。
就是操作对象使用的点语法。
如果想要修改标签元素的里面的内容,则可以使用如下几种方式:
学习路径: - document.write() 方法
- 只能将文本内容追加到 前面的位置
- 文本中包含的标签会被解析
- 对象.innerText 属性
- 将文本内容添加/更新到任意标签位置
- 文本中包含的标签不会被解析
- 对象.innerHTML 属性
- 将文本内容添加/更新到任意标签位置
- 文本中包含的标签会被解析
-
设置/修改元素常用属性
-
还可以通过 JS 设置/修改标签元素属性,比如通过 src更换 图片
-
最常见的属性比如: href、title、src 等
-
语法:
对象.属性=值
设置/修改元素样式属性
还可以通过 JS 设置/修改标签元素的样式属性。
-
通过 style 属性操作CSS
- 语法:
对象.style.样式属性=值
- 修改样式通过style属性引出
- 如果属性有-连接符,需要转换为小驼峰命名法
- element.style.
paddingLeft
= ‘300px’
- element.style.
- 赋值的时候,需要的时候不要忘记加css单位
- 语法:
-
操作类名(className) 操作CSS
- 如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式
- 语法:
元素.className='类名'
- 由于class是关键字, 所以使用className去代替
- className是使用新值换旧值, 如果需要添加一个类,需要保留之前的类名
-
通过 classList 操作类控制CSS
- 为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
- 语法:
- 追加一个类:
元素.classList.add('类名')
- 删除一个类:
元素.classList.remove('类名')
- 切换一个类:
元素.classList.toggle('类名')
-
使用 className 和classList的区别?
- 修改大量样式的更方便
- 修改不多样式的时候方便
- classList 是追加和删除不影响以前类名
-
设置/修改 表单元素 属性
表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框
正常的有属性有取值的 跟其他的标签属性没有任何区别 - 获取: DOM对象.属性名
- 设置: DOM对象.属性名 = 新值
- 表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 如果为true 代表添加了该属性 如果是false 代表移除了该属性
- 比如: disabled、checked、selected
-
定时器-间歇函数
定时器函数可以开启和关闭定时器
- 开启定时器:
setInterval(函数,间隔时间)
- 作用:每隔一段时间调用这个函数
- 间隔时间单位是毫秒
- 关闭定时器:
clearInterval('变量名')
- 定时器函数有什么作用?
- 可以根据时间自动重复执行某些代码
- 定时器函数如何开启?
- setInterval(函数名, 时间)
- 定时器函数如何关闭?
- clearInterval(变量名);
-
let 变量名 = setInterval(函数,间隔时间); clearInterval(变量名); //1.函数名字不需要加括号 //2.定时器返回的是一个id数字
COPY
事件
事件是在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件
- 语法:
元素.addEventListener('事件',要执行的函数)
- 事件监听三要素
- 事件源: 那个dom元素被事件触发了,要获取dom元素
- 事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
- 事件调用的函数: 要做什么事
-
事件类型
-
鼠标事件
- click 鼠标点击
- mouseenter 鼠标经过
- mouseleave 鼠标离开
-
焦点事件
- focus 获得焦点
- blur 失去焦点
-
键盘事件
- Keydown 键盘按下触发
- Keyup 键盘抬起触发
-
文本事件
- input 用户输入事件
-
高阶函数
高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高级应用。
【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等。 - 函数表达式
- 函数表达式和普通函数并无本质上的区别:
- 普通函数的声明与调用无顺序限制,推荐做法先声明再调用
- 函数表达式必须要先声明再调用
- 回调函数
- 如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
- 简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
- 使用匿名函数做为回调函数比较常见
- 回调函数本质还是函数,只不过把它当成参数使用
-
环境对象
环境对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁 - 函数的调用方式不同,this 指代的对象也不同
- 【谁调用, this 就是谁】 是判断 this 指向的粗略规则
- 直接调用函数,其实相当于是 window.函数,所以 this 指代 window
-
DOM节点
DOM树里每一个内容都称之为节点
节点类型 -
元素节点
- 所有的标签 比如 body、
- html 是根节点
-
属性节点
- 所有的属性 比如 href
-
文本节点
- 所有的文本
-
其他
-
查找节点
节点关系:
- 父节点、子节点、兄弟节点
-
父节点查找:
- parentNode 属性
- 返回最近一级的父节点 找不到返回为
子元素.parentNode
-
子节点查找:
- childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
- children (重点)
- 仅获得所有元素节点
- 返回的还是一个伪数组
父元素.children
-
兄弟关系查找:
- 下一个兄弟节点
- nextElementSibling 属性
- 上一个兄弟节点
- previousElementSibling 属性
-
增加节点
-
创建节点
- 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
- 创建元素节点方法:
document.createElement('标签名')
-
追加节点
-
要想在界面看到,还得插入到某个父元素中
-
插入到父元素的最后一个子元素:
-
父元素.appendChild('要插入的元素')
-
插入到父元素中某个子元素的前面
-
父元素.inserBefore('要插入的元素',在那个元素前面)
-
-
克隆节点
元素.cloneNode(布尔值)
- cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
- 若为true,则代表克隆时会包含后代节点一起克隆
- 若为false,则代表克隆时不包含后代节点
- 默认为false
-
删除节点
- 若一个节点在页面中已不需要时,可以删除它
- 在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除
- 语法:
父元素.removeChild('要删除的元素')
- 如不存在父子关系则删除不成功
- 删除节点和隐藏节点(display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点
-
时间对象
- 时间对象:用来表示时间的对象
- 作用:可以得到当前系统时间
-
实例化
- 在代码中发现了 new 关键字时,一般将这个操作称为实例化
- 获得当前时间:
let data = new Date()
- 获得当前时间:
- 创建一个时间对象并获取时间
- 获得指定时间:
let data = new Date('1948-10-01')
- 获得指定时间:
-
时间对象方法
因为时间对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
方法 作用 说明 getFullYear() 获得年份 获取四位年份 getMonth() 获得月份 取值0~10 getDate() 获取月份中的每一天 不同月份取值也不相同 getDay() 获取星期 取值为0~6 getHours() 获取小时 取值0~23 getMinutes() 获取分钟 取值0~59 getSeconds() 获取秒 取值0~59 时间戳
- 什么是时间戳
- 是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
- 三种方式获取时间戳
- 使用 getTime() 方法:
new Date().gettime()
- 简写 +new Date():
+new Date()
- 使用 Date().now():
Date().now()
- 无需实例化
- 但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳
- 重点记住 +new Date() 因为可以返回当前时间戳或者指定的时间戳
- 使用 getTime() 方法:
-
重绘和回流
- 浏览器是如何进行界面渲染的
- 解析(Parser)HTML,生成DOM树(DOM Tree)
- 同时解析(Parser) CSS,生成样式规则 (Style Rules)
- 根据DOM树和样式规则,生成渲染树(Render Tree)
- 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
- 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
- Display: 展示在页面上
- 回流(重排)
- 当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过
程称为 回流。
- 当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过
- 重绘
- 由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、
outline等), 称为重绘。 - 重绘不一定引起回流,而回流一定会引起重绘
- 会导致回流(重排)的操作:
- 页面的首次刷新
- 浏览器的窗口大小发生改变
- 元素的大小或位置发生改变
- 改变字体的大小
- 内容的变化(如:input框的输入,图片的大小)
- 激活css伪类 (如::hover)
- 脚本操作DOM(添加或者删除可见的DOM元素)
- 简单理解影响到布局了,就会有回流
-
事件对象
事件对象是什么
- 也是个对象,这个对象里有事件触发时的相关信息
- 如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
如何获取
- 在事件绑定的回调函数的第一个参数就是事件对象
-
一般命名为event、ev、e
COPY元素.addEventListener('click',function(e){ })
-
事件对象常用属性
- type
- 获取当前的事件类型
- clientX/clientY
- 获取光标相对于浏览器可见窗口左上角的位置
- offsetX/offsetY
- 获取光标相对于当前DOM元素左上角的位置
- key
- 用户按下的键盘键的值
- 现在不提倡使用keyCode
-
事件捕获和事件冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
-
事件捕获概念:从DOM的根元素开始去执行对应的事件 (从外到里)
- 事件捕获需要写对应代码才能看到效果
- 代码:
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
- ddEventListener第三个参数传入true代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
-
阻止事件流动
- 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
- 若想把事件就限制在当前元素内,就需要阻止事件流动
- 阻止事件流动需要拿到事件对象
- 语法:
事件对象.stopPropagetion()
- 此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
-
鼠标经过事件:
- mouseover 和 mouseout 会有冒泡效果
- mouseenter 和 mouseleave 没有冒泡效果(推荐)
-
阻止事件流动
- 阻止默认行为,比如链接点击不跳转,表单域的不提交
- 语法:
e.preventDefault()
-
事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
-
事件委托
- 事件委托是利用事件流的特征解决一些开发需求的知识技巧
- 总结:
- 优点:给父级元素加事件(可以提高性能)
- 原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发
- 实现:事件对象.target 可以获得真正触发事件的元素
- 事件委托是委托给了谁?
- 父元素
- 如何找到真正触发的元素?
- e.target 事件对象.target
-
滚动事件和加载事件
滚动事件
- 当页面进行滚动时触发的事件
- 为什么要学?
- 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部
- 事件名:scroll
- 监听整个页面滚动:
window.addEventListener('scroll',function(){//执行操纵})
- 监听某个元素的内部滚动直接给某个元素加即可
-
加载事件
-
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
-
为什么要学?
- 有些时候需要等页面资源全部处理完了做一些事情
- 老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到
-
事件名:load
-
监听页面所有资源加载完毕:
window.addEventListener('load',function(){})
-
注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
-
当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表
、图像等完全加载 - 事件名:DOMContentLoaded
- 监听页面DOM加载完毕:无需等待样式表、图像等完全加载
- 给 document 添加 DOMContentLoaded 事件
document.addEventListener('DOMContentLoaded',function(){})
-
元素大小和位置
scroll家族
-
使用场景:
-
我们想要页面滚动一段距离,比如100px,就让某些元素显示隐藏,那我们怎么知道,页面滚动了100像素呢?就可以使用scroll 来检测页面滚动的距离
-
获取宽高:
-
获取元素的内容总宽高(不包含滚动条)返回值不带单位
-
scrollWidth和scrollHeight
-
获取位置:
-
获取元素内容往左、往上滚出去看不到的距离
-
scrollLeft和scrollTop
-
这两个属性是可以修改的
-
-
div.addEventListener('scroll',function(){ console.log(this.scrllTop) })
COPY
-
开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素
COPYwindow.addEventListener('scroll',function(){ let num = document.documentElement.scrollTop; console.log(num); //document.documentElement HTML 文档返回对象为HTML元素 })
- scrollWidth和scrollHeight是得到元素什么的宽高?
- 内容
- 不包含滚动条
- 被卷去的头部或者左侧用那个属性?是否可以读取和修改?
- scrollTop / scrollLeft
- 可以读取,也可以修改(赋值)
- 检测页面滚动的头部距离(被卷去的头部)用那个属性?
- document.documentElement.scrollTop
offset家族
- 使用场景:
- 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。简单说,就是通过js的方式,得到元素在页面中的位置
- 获取宽高:
- 获取元素的自身宽高、包含元素自身设置的宽高、padding、border
- offsetWidth和offsetHeight
- 获取位置:
- 获取元素距离自己定位父级元素的左、上距离
- offsetLeft和offsetTop 注意是只读属性
- offsetWidth和offsetHeight是得到元素什么的宽高?
- 内容 + padding + border
- offsetTop和offsetLeft 得到位置以谁为准?
- 带有定位的父级
- 如果都没有则以 文档左上角 为准
client家族
- 获取宽高:
- 获取元素的可见部分宽高(不包含边框,滚动条等)
- clientWidth和clientHeight
-
获取位置:
- 获取左边框和上边框宽度
- clientLeft和clientTop 注意是只读属性
-
会在窗口尺寸改变的时候触发事件:
- resize
window.addEventListener('resize',function(){})
-
检测屏幕宽度:
COPYwindow.addEventListener('resize',function(){ let w = document.documentElement.cilnetWidth console.log(w) })
小结:
1.offset家族
- 获取元素自身大小:包括自身设置的宽高、padding、border
- 获取元素距离定位父级的左和上距离 只读属性
-
2.client家族
- 获取元素可见区域的大小
- 获取元素左、上边框距离 只读属性
-
3.scroll家族
- 获取元素内容的总大小
- 获取元素向左向上滚出去看不见的距离 可读写属性
-
BOM- 操作浏览器
Window对象
BOM
- BOM(Browser Object Model ) 是浏览器对象模型
- window 是浏览器内置中的全局对象,我们所学习的所有 Web APIs 的知识内容都是基于 window 对象实现的
- window 对象下包含了 navigator、location、document、history、screen 5个属性,即所谓的 BOM (浏览器对象模型)
- document 是实现 DOM 的基础,它其实是依附于 window 的属性。
- 注:依附于 window 对象的所有属性和方法,使用时可以省略 window
定时器-延时函数
- JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
- 语法:
setTimeout(回调函数,等待的毫秒数)
- setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
- 清除延时函数:
clearInterval(函数名)
COPYlet timer = setTimeout(回调函数,等待的毫秒数); clearInterval(timer);
- 结合递归函数可以使用 setTimeout 实现 setInterval 一样的功能
- 两种定时器对比:
- setInterval 的特征是重复执行,首次执行会延时
- setTimeout 的特征是延时执行,只执行 1 次
- setTimeout 结合递归函数,能模拟 setInterval 重复执行
- clearTimeout 清除由 setTimeout 创建的定时任务
swiper 插件
本地存储
-
JS 执行机制
JS 是单线程
- avaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
-
同步和异步
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
他们的本质区别: 这条流水线上各个流程的执行顺序不同。
同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS 的异步是通过回调函数实现的。一般而言,异步任务有以下三种类型:
- 普通事件,如 click、resize 等
- 资源加载,如 load、error 等
- 定时器,包括 setInterval、setTimeout 等异步任务相关添加到任务队列中(任务队列也称为消息队列)。
JS 执行机制
- 先执行执行栈中的同步任务。
- 异步任务放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
-
location对象
- location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
- 常用属性和方法:
- href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
- search 属性获取地址中携带的参数,符号 ?后面部分
- hash 属性获取地址中的啥希值,符号 # 后面部分
- reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
-
navigator对象
navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
- 常用属性和方法:
- 通过 userAgent 检测浏览器的版本及平台
COPY// 检测 userAgent(浏览器信息) !(function () { const userAgent = navigator.userAgent // 验证是否为Android或iPhone const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/) const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/) // 如果是Android或iPhone,则跳转至移动站点 if (android || iphone) { location.href = 'http://m.itcast.cn' } })()
- 通过 userAgent 检测浏览器的版本及平台
-
histroy对象
history 的数据类型是对象,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
- 常用属性和方法:
-
HISTORY 作用 back() 可以后退功能 forward() 前进功能 go(参数) 前进后退功能,参数如果是1前进1个页面
如果是-1后退1个页面 - history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。
-
本地存储
本地存储特性
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案;
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage和localStorage约 5M 左右
-
localStorage
- 生命周期永久生效,除非手动删除 否则关闭页面也会存在;
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
- 存储数据:
localStorage.setItem(key, value)
- 获取数据:
localStorage.getItem(key)
- 删除数据:
localStorage.removeItem(key)
-
存储复杂数据类型存储
本地只能存储字符串,无法存储复杂数据类型.需要将复杂数据类型转换成JSON字符串,在存储到本地
- JSON.stringify(复杂数据类型)
- 将复杂数据转换成JSON字符串 存储 本地存储中
- JSON.parse(JSON字符串)
- 将JSON字符串转换成对象 取出 时候使用
-
sessionStorage(了解)
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage 基本相同
-
自定义属性
固有属性:
标签天生自带的属性 比如class id title等, 可以直接使用点语法操作
自定义属性:
- 由程序员自己添加的属性,在DOM对象中找不到, 无法使用点语法操作,必须使用专门的API
getAttribute('属性名')
// 获取自定义属性setAttribute('属性名', '属性值')
// 设置自定义属性removeAttribute('属性名')
// 删除自定义属性-
data-自定义属性:
传统的自定义属性没有专门的定义规则,开发者随意定值,不够规范,所以在html5中推出来了专门的data-自定义属性 在标签上一律以data-开头在DOM对象上一律以dataset对象方式获取
<div class="box" data-id="10"></div> <script> let = document.querySelector('.box'); console.log(box.dataset.id);// 以dataset对象方式获取 </script>
COPY
正则表达式
什么是正则表达式
-
正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象
-
通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式
-
正则表达式在 JavaScript中的使用场景:
- 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)
- 比如用户名: /^[a-z0-9_-]{3,16}$/
- 过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等
-
JavaScript 中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:
-
定义正则表达式语法:
let 变量名 = /表达式/
; -
其中 / / 是正则表达式字面量
-
test()
方法 用来查看正则表达式与指定的字符串是否匹配 -
regObj.test(别检测的字符串)
-
如果正则表达式与指定的字符串匹配 ,返回true,否则false
-
exec()
方法 在一个指定字符串中执行一个搜索匹配 -
检索(查找)符合规则的字符串
-
regObj.exec(别检测的字符串)
-
如果匹配成功,exec() 方法返回一个数组,否则返回null
-
-
正则表达式检测查找 test方法和exec方法有什么区别?
- test方法 用于判断是否有符合规则的字符串,返回的是布尔值 找到返回true,否则false
- exec方法用于检索(查找)符合规则的字符串,找到返回数组,否则为null
-
元字符
- 边界符
- 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
-
边界符 说明 ^ 表示匹配行首文本(以谁开头) $ 表是匹配行尾文本(以谁结尾) 如果 ^ 和 $ 在一起,表示必须是精确匹配
- 量词 (表示重复次数)
- 量词用来 设定某个模式出现的次数
-
量词 说明 * 重复零次或更多次 + 重复一次或更多次 ? 重复零次或一次 {n} 重复n次 {n,} 重复n次或更多次 {n,m} 重复n到m次 注意: 逗号左右两侧千万不要出现空格
-
字符类 (比如 \d 表示 0~9)
-
[ ] 匹配字符集合
- 后面的字符串只要包含 abc 中任意一个字符,都返回 true 。
-
[ ] 里面加上 - 连字符
- 使用连字符 - 表示一个范围
- 比如:
- [a-z] 表示 a 到 z 26个英文字母都可以
- [a-zA-Z] 表示大小写都可以
- [0-9] 表示 0~9 的数字都可以
-
[ ] 里面加上 ^ 取反符号
- 比如:
- [^a-z] 匹配除了小写字母以外的字符
- 注意要写到中括号里面
- 比如:
-
.
匹配除换行符之外的任何单个字符 -
预定义:指的是某些常见模式的简写方式
-
-
预定类 说明 \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}
修饰符
-
修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
-
语法:
/表达式/修饰符
- i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
/表达式/i
- g 是单词 global 的缩写,匹配所有满足正则表达式的结果
/表达式/g
-
替换 replace 替换
- 语法:
字符串.replace(/正则表达式/,'替换的文本')
- 语法:
- 事件冒泡是默认存在的
-