JS-ECMAScript
JavaScript介绍
⚫JavaScript (是什么?)
➢是一种运行在客户端(浏览器)的编程语言,实现人机交互效果。
⚫JavaScript作用(做什么?)
1.网页特效 (监听用户的一些行为让网页作出对应的反馈)
2.表单验证 (针对表单数据的合法性进行判断)
3.数据交互 (获取后台的数据, 渲染到前端)
4.服务端编程 (node.js)
⚫JavaScript的组成(有什么?)
1、 ECMAScript:
➢规定了js基础语法核心知识。
➢比如:变量、分支语句、循环语句、对象等等
2、Web APIs :
➢DOM 操作页面中的元素,比如对页面元素进行移动、大小、添加删除等操作
➢BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等
⚫JavaScript 三种书写位置
1.外部引入方法:
⚫JavaScript 结束符
1.使用英文的 ; 代表语句结束,可写可不写
2.为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求.)
⚫JavaScript 输入输出语法
一、输出语法
语法1:
document.write ( ‘输出的内容’ )
➢作用:向body内输出内容
➢注意:如果输出的内容写的是标签,也会被解析成网页元素
语法2:
alert( ‘输出的内容’ )
➢作用:页面弹出警告对话框
语法3:
console.log( ‘控制台打印’ )
➢作用:控制台输出语法,程序员调试使用
二、输入语法
语法:
prompt( ‘请输入你的姓名’ )
➢作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字
➢通过prompt 得到的数据类型都是字符串
效果:
JavaScript 基础
⚫变量的基本使用
变量是什么?i
1. 变量是怎么理解?
➢计算机中用来存储数据的“容器”,简单理解是一个 个的盒子。
2. 变量有什么作用呢?
➢用来存放数据的。注意变量指的是容器而不是数据
一、声明变量
语法:
➢要想使用变量,首先需要创建变量(也称为声明变量或者定义变量)
➢声明变量有两部分构成:声明关键字、变量名(标识)
➢let 即关键字 (let: 允许、许可、让、要),所谓关键字是系统提供的专门用来声明(定义)变量的词语
➢变量的关键字:let、var、const
二、变量赋值
➢定义了一个变量后,你就能够初始化它(赋值)。在变量名之后跟上一个“=”,然后是数值
声明的同时赋值
三、更新变量
四、声明多个变量
五、交换变量的值
六、变量的本质
1.内存:计算机中存储数据的地方,相当于一个空间
2.变量本质:是程序在内存中申请的一块用来存放数据的小空间
七、变量命名规则与规范
1. 规则:
- 不能用关键字
- 关键字:有特殊含义的字符,JavaScript 内置的一些英语词汇。例如:let、var、if、for等
- 只能用下划线、字母、数字、$组成,且数字不能开头
- 字母严格区分大小写,如 Age 和 age 是不同的变量
2. 规范:
- 起名要有意义
- 遵守小驼峰命名法
- 多个单词时,第一个单词首字母小写,后面每个单词首字母大写。例:userName
⚫常量
➢概念:使用 const 声明的变量称为“常量”。
➢使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不是let。
➢命名规范:和变量一致
➢常量不允许重新赋值,声明的时候必须赋值(初始化)
⚫数据类型
JS 数据类型整体分为两大类:
➢基本数据类型,在存储时变量中存储的是值本身
➢引用数据类型,在存储时变量中存储的仅仅是地址(引用)
➢简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型
一、数字类型(Number)
➢JavaScript 中的正数、负数、小数等 统一称为 数字类型
➢JS 是弱数据类型,变量到底属于那种类型,只有赋值之后,我们才能确认
➢Java是强数据类型 例如 int a = 3 必须是整数
NaN 代表一个计算错误。它是一个不正确的或者一个未定义的数学操作所得到的结果
二、字符串类型(string)
1、字符串是什么?
➢通过单引号('') 、双引号( "")或反引号( ` ) 包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号。
1. 无论单引号或是双引号必须成对使用
2. 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)
3. 必要时可以使用转义符 \,输出单引号或双引号
4、字符串支持数组的下标取值
2、字符串拼接:
➢ + 运算符 可以实现字符串的拼接。
➢ 口诀:数字相加,字符相连
3、模板字符串:
➢`` (反引号)
➢在英文输入模式下按键盘的tab键上方那个键(1左边那个键)
➢内容拼接变量时,用 ${ } 包住变量
4、trim()去除字符串左右的空格
➢去除字符串左右的空格,不能去掉中间的空格
三、布尔类型(boolean)
➢表示肯定或否定时在计算机中对应的是布尔类型数据
➢它有两个固定的值 true(真)表示肯定的数据 和 false(假)表示否定的数据。
四、未定义类型(undefined)
➢只有一个值 undefined。
➢只声明变量,不赋值的情况下,变量的默认值为 undefined
➢场景:可以通过检测这个变量是不是undefined,就判断用户是否有数据传递过来
五、空类型 ( null )
➢只有一个值 null。
➢JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值
六、null 和 undefined 区别:
➢undefined 表示没有赋值
➢ null 表示赋值了,但是内容为空
七、对象 (object)
1、什么是对象
➢对象(object):JavaScript里的一种数据类型
➢可以理解为是一种无序的数据集合, 注意数组是有序的数据集合
➢可以详细的描述具体的事物
➢抽象理解:给数据起名字
➢如果我们要存储一个物体多方面的信息,就用对象。
➢如果我们要存储多个同一类别的信息,就用数组。
2、对象的使用
(1)对象语法:
let 对象名={
属性名:属性值,
函数名:函数
}
/* {} 是对象字面量 */
/* 属性:信息或叫特征(名词)。 数字型,字符型,布尔型.... */
/* 方法:功能或叫行为(动词)。函数 */
(2)属性:
➢属性都是成对出现的,包括属性名和值,它们之间使用英文 : 分隔
➢多个属性之间使用英文 , 分隔,如果名字中有特殊符号,则要加引号
➢属性就是依附在对象上的变量(外面是变量,对象内是属性)
➢属性名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
➢对象后边的键值对会覆盖前边的键值对
3、对象增删改查语法:
属性-查
语法:(3种)
(1)对象名.属性
➢使用 . 获得对象中属性对应的值.
➢不存在的属性,得到的是undefined
( 2 ) 对象[‘属性’] 方式
➢单引号和双引号都可以
➢对于多词属性或则 - 等属性,点操作就不能用了。
➢[]语法里面的值如果不添加引号 默认会当成变量解析
属性-改
➢语法:对象名.属性 = 新值
➢对象[‘新属性’] = 新值 添加多个单词的属性或者变量
属性-增
➢语法:对象名.新属性 = 新值
➢对象[‘新属性’] = 新值 添加多个单词的属性或者变量
属性-删 (了解)
➢语法:delete 对象名.属性
4、遍历对象
(1)for...in
for in 循环是一种特殊类型的循环,也是普通 for 循环的变体,主要用来遍历对象,使用它可以将对象中的属性依次循环出来,直到所有属性都遍历完
(2)遍历对象方法:
➢一般不用这种方式遍历数组、主要是用来遍历对象
➢for in语法中的 k 是一个变量, 在循环的过程中依次代表对象的属性名
➢由于 k 是变量, 所以必须使用 [ ] 语法解析
➢ k 是获得对象的属性名, 对象名[k] 是获得 属性值
(3)遍历数组对象
案例:
5、内置对象-Math
介绍:Math对象是JavaScript提供的一个“数学”对象
作用:提供了一系列做数学运算的方法
Math对象包含的方法有:
- random:生成0-1之间的随机数(包含0不包括1)
- ceil:向上取整
- floor:向下取整
- max:找最大数
- min:找最小数
- pow:幂运算
- abs:绝对值
- round: 四舍五入
内置对象-生成任意范围随机数 :
- Math.random() 随机数函数, 返回一个0 - 1之间,并且包括0不包括1的随机小数 [0, 1)(左闭右开)
案例:
八、数组 [ ]
1、数组是什么?
➢数组是一种可以按顺序保存数据的数据类型, [] 表示
2、数组的基本使用
声明语法:
例:
➢数组是按顺序保存,所以每个数据都有自己的编号
➢计算机中的编号从0开始,所以小明的编号为0,小刚编号为1,以此类推
➢在数组中,数据的编号也叫索引或下标
➢数组可以存储任意类型的数据
取值语法:
列:
➢选取数组的最后一个值:
➢通过下标取数据
➢取出来是什么类型的,就根据这种类型特点来访问
➢元素:数组中保存的每个数据都叫数组元素
➢下标:数组中数据的编号
➢长度:数组中数据的个数,通过数组的length属性获得。
3、数组增、删、改、查
(1)数组的新增
末尾添加元素:
➢数组.push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度 (重点)
语法:
开头添加元素:
➢数组.unshift(新增的内容) 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度
语法:
任意位置添加
语法:
数组.splice(位置,删除几个元素,添加的数据)
➢添加元素是 删除几个元素=0
(2)数组的删除
删除末尾元素
➢数组. pop() 方法从数组中删除最后一个元素,并返回该元素的值
语法:
删除开头元素
➢数组. shift() 方法从数组中删除第一个元素,并返回该元素的值
语法:
删除指定元素
语法:
start 起始位置:
➢指定修改的开始位置(从0计数,数组的下标)
deleteCount:
➢表示要移除的数组元素的个数
➢可选的。 如果省略则默认从指定的起始位置删除到最后
4、数组中join方法
作用:
➢join() 方法用于把数组中的所有元素转换一个字符串
语法:
➢数组元素是通过参数里面指定的分隔符进行分隔的
5、数组方法
1、for循环
2、迭代数组map方法
语法:
➢map 可以处理数据,并且返回新的数组
➢可以用来循环遍历数组
➢map 也称为映射,也就是原数组被“映射”成对应新数组
➢这个新数组:由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
➢map() 不会对空数组进行检测。
➢map() 不会改变原始数组。
3、遍历数组 forEach 方法(重点)
语法:
1、forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数
2、forEach() 方法对数组的每个元素执行一次提供的函数。
3、forEach 主要是遍历数组
4、参数当前数组元素是必须要写的, 索引号可选
5、传递参数的时候,可以使用对象解构
4、筛选数组 filter 方法(重点)
语法:
1、filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
2、返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组
3、参数:currentValue 必须写, index 可选
4、因为返回新数组,所以不会影响原数组
九、检测数据的类型 ( typeof )
typeof 运算符可以返回被检测的数据类型。它支持两种语法形式:
➢ 作为运算符: typeof x (常用的写法)
➢ 函数形式: typeof(x)
十、数据类型的存储
1、栈(操作系统):
- 由操作系统自动分配释放存放函数的参数值、局部变量的值等。
- 简单数据类型变量的数据直接存放在变量(栈空间)中
2、堆(操作系统):
- 引用类型(复杂数据类型):通过关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
- 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
术语解释 :
⚫数据类型的转变
一、隐式转换
➢ + 号两边只要有一个是字符串,都会把另外一个转成字符串
➢除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
二、转换为数字型
1、+号作为正号解析可以转换成数字型
2、Number(数据) ;
➢ 转成数字类型
➢ 如果字符串内容里有非数字,转换失败时结果为 NaN(Not a Number)即不是一个数字
➢ NaN也是number类型的数据,代表非数字
3、parseInt (数据) ;
➢ 只保留整数
4、parseFloat (数据) ;
➢ 可以保留小数
三、转换为字符型:
➢String(数据)
四、转换为Boolean型
1、Boolean(内容)
➢ 记忆:' ' 、0、undefined、null、false、NaN 转换为布尔值后都是false, 其余则为 true
⚫运算符
一、算术运算符:
➢ +:求和
➢ -:求差
➢ *:求积
➢ /:求商
➢ %:取模(取余数)
二、赋值运算符
1、已经学过的赋值运算符:= 将等号右边的值赋予给左边, 要求左边必须是一个容器
2、其他赋值运算符:
➢ += ➢ -= ➢*= ➢ /= ➢ %=
➢ num += 5 --------> num = nam+5
三、比较运算符
➢从左往右依次比较
➢NaN不等于任何值,包括它本身,涉及到"NaN“ 都是false
➢尽量不要比较小数,因为小数有精度问题
➢不同类型之间比较会发生隐式转换,最终把数据隐式转换转成number类型再比较
四、逻辑运算符
写法:num > 5 && num < 10
逻辑运算符:
六、运算符优先级
七、一元运算符 (了解)
➢例: 正负号
1、自增:
➢符号:++
➢作用:让变量的值 +1
➢先自加,在使用
2、自减:
➢符号:--
➢作用:让变量的值 -1
➢先使用,再自加
➢使用场景:经常用于计数来使用。 比如进行10次操作,用它来计算进行了多少次了
特点:
➢每执行1次,当前变量数值加1
⚫语句
1、表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧。
释义:
➢表达式 : num = 3 + 4
2、语句:语句不一定有值,所以比如 alert() for和break 等语句就不能被用于赋值。
释义:
➢语句 :alert() 弹出对话框 、console.log() 控制台打印输出
➢某些情况,也可以把表达式理解为表达式语句,因为它是在计算结果,但不是必须的成分 (例如continue语句)
一、if分支语句
释义:
if语句
➢if语句有三种使用:单分支、双分支、多分支
1、单分支使用语法:
if (条件){
满足条件需要执行的代码
}
释义:
➢括号内的条件为true时,进入大括号里执行代码
➢小括号内的结果若不是布尔类型时,会发生隐式转换转为布尔类型
➢通常用于范围判断
2、双分支if语法:
if (条件){
满足条件执行的代码
} else{
不满足条件执行的代码
}
释义:
➢else 表示“否则”的意思
3、多分支if语法:
if(条件1){
满足条件执行的代码
} else if(条件2){
代码二
} else if(条件2){
代码三
}else(条件2){
代码n
}
释义:
➢先判断条件1,若满足条件1就执行代码1,其他不执行
➢若不满足则向下判断条件2,满足条件2执行代码2,其他不执行
➢若依然不满足继续往下判断,依次类推
➢若以上条件都不满足,执行else里的代码n
二、三元运算符
三元运算符语法:
条件 ? 满足条件执行的代码 : 不满足条件执行的代码
释义:
➢使用场景:比 if 双分支 更简单的写法,可以使用 三元表达式
➢? 和 : 配合使用
➢一般用来取值
三、switch 多分支结构
switch 语法:
switch(数据){
case 值1:
代码1
break //退出
case 值2:
代码2
break
default:
代码n
break
}
释义:
➢找到跟小括号里的数据全等的case值,并执行里边的代码
➢若没有全等===的则执行default里的代码
➢数据若跟值2全等,则执行代码2
➢ switch case语句一般用于等值判断,不适合于区间判断
➢switch case一般需要配合break关键字使用 没有break会造成case穿透
➢通常处理一些比较确定的值的情况
四、while 循环语句
1、while 循环基本语法:
while (循环条件) {
要重复执行的代码(循环体)
}
释义:
➢跟if语句很像,都要满足小括号里的条件为true才会进入 循环体 执行代码
➢while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,直到括号内条件不满足,即跳出
2、while 循环三要素:
3、退出循环:
➢ break:跳出所在的循环,退出整个循环
➢ continue:结束本次循环,继续下次循环
➢break 和 continue一般都会放在 if 条件判断中进行使用
五、for循环
1. for循环语法
➢作用:重复执行代码
➢好处:把声明起始值、循环条件、变化值写到一起,让人一目了然,它是最常使用的循环形式
2. 退出循环
➢continue 退出本次循环,一般用于排除或者跳过某一个选项的时候, 可以使用continue
➢ break 退出整个for循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用
3、for循环和while循环有什么区别呢:
➢当如果明确了循环的次数的时候推荐使用for循环
➢当不明确循环的次数的时候推荐使用while循环
4、for 循环嵌套
判断一个数是不是质数
⚫函数
说明:
➢function,是被设计为执行特定任务的代码块
➢函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑
一、函数的使用
1、函数的声明语法:
function 函数名 () {
函数体
}
2、函数名命名规范 :
➢和变量命名基本一致
➢尽量小驼峰式命名法
➢前缀应该为动词
➢命名建议:常用动词约定
3、函数的调用:
语法:
函数名(数据 )
➢声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数
二、函数传参
1、声明语法:
function 函数名 (参数列表) {
函数体
}
参数列表 :
➢声明这个函数需要传入几个数据
➢传入数据列表,多个数据用逗号隔开
2、调用语法:
函数名 (传递的参数列表)
➢调用函数时,需要传入几个数据就写几个,用逗号隔开
➢每一次函数调用,都会完整的执行函数体内部的代码,每一次函数调用都是互相独立的。
3、函数参数分类:
➢形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
➢实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
➢形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
➢尽量保持形参和实参的个数一致
➢有参数会优先执行传递过来的实参, 否则默认为 undefined
参数默认值:
➢用户不输入实参,可以给形参默认值,可以默认为 0, 这样程序更严谨
三、函数的返回值
1、有返回值函数的概念:
➢当调用某个函数,这个函数会返回一个结果出来,这就是有返回值的函数
2、函数返回值:
语法: return 数据
3、有返回值的函数
细节:
➢在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
➢return 后面代码不会再被执行,会立即结束当前函数,所以 return 后面的数据不要换行写
➢函数可以没有 return,这种情况函数默认返回值为 undefined
➢return 的值返回给函数的调用者,
4、函数细节补充
➢两个相同的函数后面的会覆盖前面的函数
➢在Javascript中 实参的个数和形参的个数可以不一致
➢如果形参过多 会自动填上undefined (了解即可)
➢如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
➢函数一旦碰到return就不会在往下执行了 函数的结束用return
四、作用域
1、释义:
➢通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
2、根据作用域的不同,变量可以分为:
➢全局变量:函数外部 let 的变量,在任何区域都可以访问和修改
➢局部变量:函数内部 let 的变量,只能在函数内部访问和修改
3、特殊情况:
➢参数也是局部变量
➢大括号{ }里的变量也是局部变量
➢如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
4、变量的访问原则 :
➢访问原则:先局部, 局部没有再找全局,就近原则。
➢如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
五、匿名函数
1、分类:
➢具名函数的调用可以写到任何位置
2、函数表达式
➢将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
语法:
let fn = function ( ){
//函数体
}
调用:
fn ( ) //函数名
➢其中函数的形参和实参使用跟具名函数一致
3、立即执行函数
➢无需调用,立即执行,其实本质已经调用了
➢多个立即执行函数之间用分号隔开,要不然会报错
➢函数必须写在小括号里边
六、逻辑运算符里的短路
短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行
➢原因:通过左边能得到整个式子的结果,因此没必要再判断右边
➢运算结果:无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值
web API
⚫Web API 基本认知
变量声明
1. 以后声明变量我们优先使用哪个?
➢ const
➢有了变量先给const,如果发现它后面是要被修改的,再改为let
2. 为什么const声明的对象可以修改里面的属性?
➢因为对象是引用类型,里面存储的是地址,只要地址不变,就不会报错
➢建议数组和对象使用 const 来声明
3. 什么时候使用let声明变量?
➢如果基本数据类型的值或者引用类型的地址发生变化的时候,需要用let
比如 一个变量进行加减运算,比如 for循环中的 i++
BOM
⚫DOM
一、什么是DOM
1. Web API阶段我们学习那两部分?
➢ DOM
➢ BOM
2. DOM 是什么?有什么作用?
➢ DOM 是文档对象模型
➢DOM是浏览器提供的一套专门用来 操作网页内容 的功能
➢ 操作网页内容,可以开发网页内容特效和实现用户交
互
二、DOM树
1、DOM树是什么 ?
➢将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
➢作用:文档树直观的体现了标签与标签之间的关系
三、DOM对象(重要)
1、DOM对象是什么?
➢浏览器根据html标签生成的 JS对象
2、DOM的核心思想
➢把网页内容当做对象来处理
3、document 对象
➢是 DOM 里提供的一个对象
➢所以它提供的属性和方法都是用来访问和操作网页内容的
例:document.write()
➢网页所有内容都在document里面
四、获取DOM对象
1、根据CSS选择器来获取DOM元素 (重点)
(1)选择匹配的第一个元素
语法: document.querySelector('css选择器')
参数:
➢包含一个或多个有效的CSS选择器 字符串
返回值:
➢CSS选择器匹配的第一个元素,一个 HTMLElement对象。 如果没有匹配到,则返回null。
(2)选择匹配的多个元素
语法:
document.querySelectorAll('css选择器')
参数:
➢包含一个或多个有效的CSS选择器 字符串
返回值:
➢CSS选择器匹配的NodeList 对象集合
得到的是一个伪数组:
➢有长度有索引号的数组
➢但是没有 pop() push() 等数组方法
➢想要得到里面的每一个对象,则需要遍历(for)的方式获得。
2、其他获取DOM元素方法(了解)
五、操作元素内容
1. 对象.innerText 属性
➢用于获取或替换 HTML 元素的内容
➢只识别文本,不能解析标签
2. 对象.innerHTML 属性
➢用于获取或替换 HTML 元素的内容
➢能识别文本,能够解析标签
➢多标签建议使用模板字符
六、操作元素属性
1、操作元素常用属性
➢通过 JS 设置/修改标签元素属性,比如通过 src更换 图片,最常见的属性比如: href、title、src 等
语法:
➢对象.属性=值
2、操作元素样式属性
(1)通过 style 属性操作CSS
语法:
对象.style.样式属性 = 值
➢修改样式通过style属性引出
➢如果属性有-连接符,需要转换为小驼峰命名法
➢赋值的时候,需要的时候不要忘记加css单位
(2)操作类名(className) 操作CSS
语法:
➢由于class是关键字, 所以使用className去代替
➢直接使用 className 赋值会覆盖以前的类名
(3)通过 classList 操作类控制CSS
语法:
➢切换一个类名类,有这个类名就删除,没有就加上
➢classList 是追加和删除不影响以前类名
➢classList.contains() 看看有没有包含某个类,如果有则返回true,没有则返回false
3、操作 表单元素 属性 :checked 选择器
➢表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 (属性值只有两种结果,一般用布尔类型表示)
➢如果为true 代表添加了该属性 如果是false 代表移除了该属性
比如: disabled(禁用)、checked、selected (disabled 属性规定应该禁用 input 元素。
被禁用的 input 元素既不可用,也不可点击。可以设置 disabled 属性,直到满足某些其他的条件为止)
➢:checked 选择器匹配每个选中的输入元素(仅适用于单选按钮或复选框)
➢元素.reset() :清空表单,重置
4、自定义属性
标准属性:
➢标签天生自带的属性 比如class id title等, 可以直接使用点语法操作比如: disabled、checked、selected
自定义属性:
➢在html5中推出来了专门的data-自定义属性
➢在标签上一律以data-开头
➢在DOM对象上一律以dataset对象方式获取
➢一组元素能各自独立进行两种状态之间的相互切换
七、定时器-间歇函数 setinterval (函数,间隔时间)
➢定时器函数可以根据时间自动重复执行某些代码
➢定时器函数可以开启和关闭定时器
开启定时器:setinterval (函数,间隔时间)
➢作用:每隔一段时间调用这个函数
➢间隔时间单位是毫秒
关闭定时器:
⚫Dom事件基础
一、事件监听(绑定)
什么是事件?
事件是在编程时系统内发生的动作或者发生的事情比如用户在网页上单击一个按钮
什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等
1、事件监听 addEventListener
语法:元素对象. addEventListener ('事件类型' ,要执行的函数)
事件监听三要素:
➢事件源:那个dom元素被事件触发了,要获取dom元素
➢事件类型:用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
➢事件调用的函数: 要做什么事
2、事件监听版本
DOM L0
➢事件源.on事件 = function() { }
DOM L2
➢事件源.addEventListener(事件, 事件处理函数)
两者区别:
➢on方式会被覆盖,addEventListener方式可绑定多次,拥有事件更多特性,推荐使用
二、事件类型
1、鼠标事件
2、焦点事件
3、键盘事件
4、文本事件
鼠标经过事件:
➢ mouseenter 和 mouseleave 没有冒泡效果 (推荐)
➢ mouseover 和 mouseout 会有冒泡效果
➢submit当提交表单时,会发生 submit 事件,该事件只适用于 <form> 元素。
➢change当鼠标离开了表单,并且表单值发生变化时触发
➢mousemove 鼠标移动事件
➢ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
➢onloadeddata 事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的下一帧时触发
三、事件对象
1、事件对象是什么 ?
➢也是个对象,这个对象里有事件触发时的相关信息
➢例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
2、使用场景
➢可以判断用户按下哪个键,比如按下回车键可以发布新闻
➢可以判断鼠标点击了哪个元素,从而做相应的操作
3、语法:如何获取
4、常见事件对象属性
type
➢获取当前的事件类型
clientX/clientY
➢获取光标相对于浏览器可见窗口左上角的位置
offsetX/offsetY
➢获取光标相对于当前DOM元素左上角的位置
key
➢用户按下的键盘键的值
➢现在不提倡使用keyCode
target
➢触发事件的元素
target.tagName
➢事件对象.target.tagName触发事件的大写标签
四、环境对象 this
环境对象:指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁
➢函数的调用方式不同,this 指代的对象也不同
➢【谁调用, this 就是谁】 是判断 this 指向的粗略规则
➢直接调用函数,其实相当于是 window.函数,所以 this 指代 window
五、回调函数
1、什么是回调函数?
➢如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
2、常见使用常数
➢把函数当做另外一个函数的参数传递,这个函数就叫回调函数
➢回调函数本质还是函数,只不过把它当成参数使用
➢使用匿名函数做为回调函数比较常见
六、事件流
1、事件流和两个阶段说明
➢事件流指的是事件完整执行过程中的流动路径
➢说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
➢简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
➢实际工作都是使用事件冒泡为主
2、事件捕获
事件捕获概念:
➢从DOM的根元素开始去执行对应的事件 (从外到里)
事件捕获需要写对应代码才能看到效果
代码:
元素对象. addEventListener ('事件类型' ,要执行的函数,是否使用捕获机制)
说明:
➢addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
➢若传入false代表冒泡阶段触发,默认就是false
➢若是用 L0 事件监听,则只有冒泡阶段,没有捕获
3、事件冒泡
事件冒泡概念:
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
➢简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
➢事件冒泡是默认存在的
➢L2事件监听第三个参数是 false,或者默认都是冒泡
4、阻止冒泡 阻止元素默认行为
前提:
➢阻止事件冒泡需要拿到事件对象
语法:阻止冒泡
事件对象.stopPropagation( )
➢此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
场景:
➢我们某些情况下需要阻止元素默认行为的发生,比如 阻止 链接的跳转,表单域跳转
语法:阻止元素默认行为
事件对象.preventDefault( )
5、解绑事件
传统on注册(L0):
➢on事件方式,直接使用null覆盖偶就可以实现事件的解绑
语法:
事件监听注册(L2):
addEventListener方式,必须使用:
removeEventListener(事件类型, 事件处理函数 [,获取捕获或者冒泡阶段])
例如:
两种注册事件的区别
传统on注册:
➢同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
➢直接使用null覆盖偶就可以实现事件的解绑
➢都是冒泡阶段执行的
事件监听注册:
➢语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
➢后面注册的事件不会覆盖前面注册的事件(同一个事件)
➢可以通过第三个参数去确定是在冒泡或者捕获阶段执行
➢必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
➢匿名函数无法被解绑
七、事件委托
事件委托是利用事件流的特征解决一些开发需求的知识技巧
➢优点:减少注册次数,可以提高程序性能
➢原理:事件委托其实是利用事件冒泡的特点。
➢给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
➢实现:事件对象.target. tagName 可以获得真正触发事件的元素
八、其他事件
1、页面加载事件load
(1)load
➢加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
事件名:load
➢监听页面所有资源加载完毕:
➢给 window 添加 load 事件
注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
(2)DOMContentLoaded
➢当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载
事件名:DOMContentLoaded
➢监听页面DOM加载完毕:
➢给 document 添加 DOMContentLoaded 事件
2、元素滚动事件 scroll --- 重点
➢滚动条在滚动的时候持续触发的事件
➢很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部
(1)事件名:scroll
➢监听整个页面滚动:
➢给 window 或 document 添加 scroll 事件
➢监听某个元素的内部滚动直接给某个元素加即可
(2)属性:
scrollLeft和scrollTop (属性)
➢获取被卷去的大小
➢获取元素内容往左、往上滚出去看不到的距离
➢这两个值是可读写的
➢尽量在scroll事件里面获取被卷去的距离
➢document.documentElement HTML 文档返回对象为HTML元素
(3)scrollTo() 方法可把内容滚动到指定的坐标
语法:元素.scrollTo(x, y)
例如:
3、页面尺寸事件 resize
会在窗口尺寸改变的时候触发事件:
➢ resize
检测屏幕宽度:
获取宽高:
➢获取元素的可见部分宽高(不包含边框,margin,滚动条等)
➢clientWidth和clientHeight
4、元素尺寸与位置 offset...
使用场景:
➢前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。
➢简单说,就是通过js的方式,得到元素在页面中的位置
➢这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
获取宽高:
➢获取元素的自身宽高、包含元素自身设置的宽高、padding、border
➢offsetWidth和offsetHeight
➢获取出来的是数值,方便计算
➢注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0
获取位置:
➢获取元素距离自己定位父级元素的左、上距离
➢ offsetLeft和offsetTop 注意是只读属性
- 获取元素距离自己定位父级元素的左、上距离
➢element.getBoundingClientRect() --- 了解
- 方法返回元素的大小及其相对于视口的坐标位置
总结:
九、日期对象
1、实例化
在代码中发现了 new 关键字时,一般将这个操作称为实例化
➢获得当前时间
new Date()
➢获得指定时间
new Date('2000-1-21 08:00:00')
2、日期对象方法
使用场景:因为日期对象返回的数据我们不能直接使用,所以我们需要转换为实际开发中常用的格式
➢getFullYear() --- 获得年份,获取四位年份
➢getMonth() --- 获得月份,取值为 0 - 11
➢getDate() --- 获取月份中的每一天,不同的月份取值也不同
➢getDay() --- 获取星期,取值为 0 - 6,0代表星期日
➢getHours() --- 获取小时,取值为0 - 23
➢getMinutes --- 获取分钟,取值为 0 - 59
➢getSeconds --- 获取秒,取值为 0 - 59
案例:打印出此时的年、月、日、时、分、秒+
3、时间戳
什么是时间戳:
➢指从格林威治时间1970年01月01日00时00分00秒(UTC/GMT的午夜)起至现在的总秒数。时间戳通常是一个字符序列,唯一地标识某一刻的时间。
算法:
➢将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数
➢剩余时间毫秒数 转换为 剩余时间的 年月日时分秒 就是 倒计时时间
➢比如 将来时间戳 2000ms - 现在时间戳 1000ms = 1000ms
➢1000ms 转换为就是 0小时0分1秒
三种方式获取时间戳:
(1)使用 getTime() 方法
new Date().getTime()
(2)简写 +new Date()
+new Date()
(3)使用 Date.now()
Date.now()
➢无需实例化
➢但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳
十、节点操作
1、DOM 节点
DOM节点
➢DOM树里每一个内容都称之为节点
节点类型
➢元素节点
- 所有的标签 比如 body、 div
- html 是根节点
➢属性节点
- 所有的属性 比如 href
➢文本节点
- 所有的文本
➢其他
2、查找节点
(1)父节点
➢parentNode 属性
➢返回最近一级的父节点 找不到返回为null
子元素.parentNode
(2)子节点
➢childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
➢children 属性 (重点)
- 仅获得所有元素节点
- 返回的还是一个伪数组
父元素.children
(3)兄弟节点
➢下一个兄弟节点
同级元素.nextElementSibling 属性
➢上一个兄弟节点
同级元素. previousElementSibling 属性
3、增加节点
很多情况下,我们需要在页面中增加元素
➢比如,点击发布按钮,可以新增一条信息
一般情况下,我们新增节点,按照如下操作:
➢创建一个新的节点
➢把创建的新的节点放入到指定的元素内部
(1)创建节点
➢即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
➢创建元素节点方法:
document.createElement ('标签名')
(2)追加节点
➢要想在界面看到,还得插入到某个父元素中
➢插入到父元素的最后一个子元素:
父元素.appendChild(要添加的元素)
➢插入到父元素中某个子元素的前面
父元素.insertBefore(要添加的元素,在那个元素前边)
(3)克隆节点
特殊情况下,我们新增节点,按照如下操作:
➢复制一个原有的节点
➢把复制的节点放入到指定的元素内部
父元素.cloneNode(布尔值)
➢cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
➢若为true,则代表克隆时会包含后代节点一起克隆
➢若为false,则代表克隆时不包含后代节点
➢默认为false
4、删除节点
语法:父元素.removeChild(要删除的元素)
➢删除元素必须通过父节点,如果不存在父子关系则删除不成功
语法:元素.remove()
➢删除元素自身
十一、M端事件(了解)
➢touch 对象代表一个触摸点,触屏事件可以响应用户手指(或触摸笔)对屏幕或者对触控板操作
十二、JS插件
➢插件:就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果。
十三、重绘和回流
回流(重排):
➢当 Render Tree(渲染树的结构)中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或者全部文档的过程称为 回流
会导致回流(重排)的操作:
页面的首次刷新、浏览器的窗口大小发生改变、元素的大小或位置发生改变、改变字体的大小、内容的变化(如:input框的输入,图片的大小)、激活css伪类 (如::hover)、脚本操作DOM(添加或者删除可见的DOM元素)
重绘:
➢由于节点的样式的改变并不影响他在文档中的位置和文档布局时(比如:color、backgruound、outline等),称为重绘
重绘不一定引起回流,但回流一定会引起重绘。
BOM
⚫BOM(浏览器对象模型)
一、什么是BOM
➢BOM是浏览器对象模型
➢window对象是一个全局对象,也可以说是JavaScript中的顶级对象
➢像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的。
➢window对象下的属性和方法的调用都可省略window
二、定时器-延时函数
➢JavaScript内置的一个用来让代码延迟执行的函数,叫setTimeout
语法:
setTimeout(回调函数,等待的毫秒数)
➢setTimeout仅仅只执行一次,就是把一段代码延迟执行
清除延时函数:
let timer = setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)
➢延迟器需要等待,所以后面的代码先执行
➢每一次调用延迟器都会产生一个新的延迟器
三、JS执行机制
➢JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。
同步
➢前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
同步任务
➢同步任务都在主线程上执行,形成一个执行栈。
异步
➢你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。
异步任务
➢JS 的异步是通过回调函数实现的。
➢异步任务相关添加到任务队列中(任务队列也称为消息队列)。
事件循环
1. 先执行执行栈中的同步任务。
2. 异步任务放入任务队列中。
3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
四、location对象
➢location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
常用属性和方法:
1.href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转
2.search 属性获取地址中携带的参数,符号 ?后面部分
3.hash 属性获取地址中的啥希值,符号 # 后面部分
4.reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新
五、navigator对象
navigator.userAgent(了解)
➢用户代理:返回当前用户的设备和浏览器版本信息
➢应用场景:前端可以根据设备信息判断用户使用的是手机还是电脑,从而跳转相应的页面
六、histroy对象
➢history 的数据类型是对象,主要管理历史记录
常用属性和方法:
1、history.back()
➢后退
2、history.forward()
➢前进
3、history.go(参数)
➢参数如果是1前进一个页面
➢参数如果是-1 后退一个页面
七、本地存储(重点)
1、本地存储介绍 (作用)
➢保存数据到本地,刷新页面不丢失
➢可以存储大小5M 左右
2、本地存储-localStorage
作用:
➢可以将数据永久存储在本地(用户的电脑), 除非手动删除,否则关闭页面也会存在
特性:
➢可以多窗口(页面)共享(同一浏览器可以共享)
➢以键值对的形式存储使用
语法:
存储数据:(增,改)
localStorage.setItem('key','value')
获取数据:(查)
localStorage.getItem('key')
删除数据:(删)
localStorage.removeItem('key')
3、本地存储分类- sessionStorage
特性:
➢生命周期为关闭浏览器窗口
➢在同一个窗口(页面)下数据可以共享
➢以键值对的形式存储使用
➢用法跟localStorage 基本相同
4、存储复杂数据类型-JSON
➢本地存储只能存储字符串
➢如果存储复杂数据类型,需要将复杂数据类型转换成JSON字符串,在存储到本地
语法:
JSON.stringify(复杂数据类型)
➢JSON是一种字符串的特殊格式,和JS数组和对象非常像
➢所有引号都是双引号
➢所有的键必须加双引号
5、把取出来的字符串转换为对象
解决:
➢把取出来的字符串转换为对象
语法:
JSON.parse(JSON字符串)
十、正则表达式
1、什么是正则表达式?
➢正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。
➢正则表达式也是一个对象。
➢通常用来查找、替换那些符合正则表达式的文本。
➢使用场景:表单内只能输入英文、中文(匹配),过滤页面敏感词(替换),获取我们想要的特定部分(提取)
2、语法
定义正则表达式
语法:
const 变量名 = / 表达式/
➢其中/ /是正则表达式字面量
判断是否有符合规则的字符串
语法:
regObj.test(被检测的字符串)
➢test() 方法 用来查看正则表达式与指定的字符串是否匹配
➢如果正则表达式与指定的字符串匹配,返回true,否则false
检索(查找)符合规则的字符串
语法:
regObj.exec(被检测的字符串)
➢exec() 方法 在一个指定字符串中执行一个搜索匹配
➢如果匹配成功,返回一个数组,否则返回null
3、元字符
分类:
➢边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)
➢量词 (表示重复次数)
➢字符类 (比如 \d 表示 0~9)
边界符
➢正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
➢如果 ^ 和 $ 在一起,表示必须是精确匹配
量词
➢量词用来 设点某个模式出现的次数
➢逗号左右两侧千万不要出现空格
字符类
[ ] 匹配字符集合
➢[ ] 里面加上 ^ 取反符号,比如: [^a-z] 匹配除了小写字母以外的字符
➢点 . 匹配除换行符之外的任何单个字符
➢使用连字符 - 表示一个范围
比如:
➢[a-z] 表示 a 到 z 26个英文字母都可以
➢[a-zA-Z] 表示大小写都可以
➢[0-9] 表示 0~9 的数字都可以
字符类预定义:
➢指的是 某些常见模式的简写方式。
4、修饰符
➢修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
语法:
/表达式/修饰符
➢i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
➢g 是单词 global 的缩写,匹配所有满足正则表达式的结果
replace 替换
字符串.replace(/正则表达式/,'替换的文本')
JS提高阶段
一、作用域
1、局部作用域
➢局部作用域分为函数作用域和块作用域
函数作用域:
➢在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。
➢函数的参数也是函数内部的局部变量
➢不同函数内部声明的变量无法互相访问
➢函数执行完毕后,函数内部的变量实际被清空了
块作用域:
➢在 JavaScript 中使用 { } 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问
➢let 声明的变量会产生块作用域,var 不会产生块作用域
➢const 声明的常量也会产生块作用域
➢不同代码块之间的变量无法互相访问
2、全局作用域
➢<script> 标签 和 .js 文件 的最外层就是所谓的全局作用域
➢全局作用域中声明的变量,任何其它作用域都可以被访问
➢为 window 对象动态添加的属性默认也是全局的,不推荐!
➢函数中未使用任何关键字声明的变量为全局变量,不推荐!!!
➢尽可能少的声明全局变量,防止全局变量被污染
3、作用域链
➢嵌套关系的作用域串联起来形成了作用域链
➢作用域链本质上是底层的变量查找机制。
➢在函数被执行时,会优先查找当前函数作用域中查找变量
➢如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域
➢子作用域能够访问父作用域,父级作用域无法访问子级作用域
4、JS垃圾回收机制
什么是垃圾回收机制
➢垃圾回收机制(Garbage Collection) 简称 GC
➢JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。
➢不再用到的内存,没有及时释放,就叫做内存泄漏
内存的生命周期:
JS环境中分配的内存, 一般有如下生命周期:
1. 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
2. 内存使用:即读写内存,也就是使用变量、函数等
3. 内存回收:使用完毕,由垃圾回收自动回收不再使用的内存
说明:
➢全局变量一般不会回收(关闭页面回收);
➢一般情况下局部变量的值, 不用了, 会被自动回收掉
垃圾回收的算法说明
➢所谓垃圾回收, 核心思想就是如何判断内存是否已经不再会被使用了, 如果是, 就视为垃圾, 释放掉 。
下面介绍两种常见的浏览器垃圾回收算法: 引用计数法 和 标记清除法
引用计数 :
➢IE采用的引用计数算法, 定义“内存不再使用”的标准很简单,就是看一个对象是否有指向它的引用
算法:
1. 跟踪记录每个值被引用的次数。
2. 如果这个值的被引用了一次,那么就记录次数1
3. 多次引用会累加。
4. 如果减少一个引用就减1。
5. 如果引用次数是0 ,则释放内存
➢但它却存在一个致命的问题:嵌套引用。
➢如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄露
标记清除法:
现代浏览器通用的大多是基于标记清除算法的某些改进算法
核心:
1. 标记清除算法将“不再使用的对象”定义为“无法达到的对象”。
2. 就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象。 凡是能从根部到达的对象,都是还需要使用的。
3. 那些无法由根部出发触及到的对象被标记为不再使用,稍后进 行回收。
5、闭包
➢概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
➢简单理解:闭包 = 内层函数 + 外层函数的变量
➢闭包作用:封闭数据,提供操作,外部也可以访问函数内部的变量
闭包应用:实现数据的私有
6、变量提升
➢变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)
注意:
1. 变量在未声明即被访问时会报语法错误
2. 变量在var声明之前即被访问,变量的值为 undefined
3. let/const 声明的变量不存在变量提升
4. 变量提升出现在相同作用域当中
5. 实际开发中推荐先声明再访问变量
二、函数进阶
1、函数提升
➢函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
1. 函数提升能够使函数的声明调用更灵活
2. 函数表达式不存在提升的现象
3. 函数提升出现在相同作用域当中
2、函数参数
动态参数
➢arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
总结:
1. arguments 是一个伪数组,只存在于函数中
2. arguments 的作用是动态获取函数的实参
3. 可以通过for循环依次得到传递过来的实参
剩余参数
1. ... 是语法符号,置于最末函数形参之前,用于获取多余的实参
2. 借助 ... 获取的剩余实参,是个真数组
展开运算符
➢展开运算符(…),将一个数组进行展开
➢典型运用场景: 求数组最大值(最小值)、合并数组等
➢不会修改原数组
剩余参数:函数参数使用,得到真数组
展开运算符:数组中使用,数组展开
3、箭头函数
(1)箭头函数
使用场景:箭头函数更适用于那些本来需要匿名函数的地方
基本写法 :
简洁写法:
➢只有一个参数可以省略小括号
➢如果函数只有一行代码,可以写在一行上,并且无需写 {} 和return,直接返回值
➢加括号的函数体返回对象字面量表达式
➢加括号的函数体返回对象字面量表达式
(2)箭头函数参数
➢普通函数有arguments 动态参数
➢箭头函数没有 arguments 动态参数,但是有 剩余参数 ...args
(3)箭头函数 this
➢箭头函数不会创建自己的this,他只会从自己的作用域链的上一层沿用this
4、解构赋值
(1)数组解构
基本语法:
1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
2. 变量的顺序对应数组单元值的位置依次进行赋值操作
3. 数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法
4. 变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
5. 允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效
(2)对象解构
基本语法:
1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
2. 对象属性的值将被赋值给与属性名相同的变量
3. 注意解构的变量名不要和外面的变量名冲突否则报错
4. 对象中找不到与变量名一致的属性时变量值为 undefined
给新的变量名赋值: 冒号表示“什么值:赋值给谁”
多级对象解构:
三、构造函数
1、构造函数
(1)构造函数:
构造函数:是一种特殊的函数,主要用来初始化对象
使用场景:可以通过构造函数创建多个类似的对象
➢构造函数在技术上是常规函数。
➢使用 new 关键字调用函数的行为被称为实例化
➢构造函数内部无需写 return ,返回值即为新创建的对象
➢new Object() new Date() 也是实例化构造函数
不过有两个约定:
➢它们的命名以大写字母开头。
➢它们只能由 "new" 操作符来执行。
(2)实例化执行过程
说明:
1. 创建新对象
2. 构造函数this指向新对象
3. 执行构造函数代码,修改this,添加新的属性
4. 返回新对象
(3)实例成员和静态成员
实例成员:
1、通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。
2、为构造函数传入参数,动态创建结构相同但值不同的对象
3. 构造函数创建的实例对象彼此独立互不影响。
静态成员:
1、构造函数的属性和方法被称为静态成员
(4)编程思想
面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再依次调用就可以了。/ 优点:性能比面向对象高,适合跟硬件联系很紧密的东西。/ 缺点:没有面向对象易维护、易复用、易扩展 。
面向对象:在面向对象程序开发思想中,每一个对象都是功能中心,具有明确的分工。具有灵活、代码可复用、容易维护和开发的优点。/ 特征:封装性、继承性、多态性。/ 缺点:性能比面向过程低
(5)构造函数的封装
➢封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。
➢借助构造函数创建出来的实例对象之间是彼此不影响的
➢前面我们学过的构造函数方法很好用,但是 存在浪费内存的问题
2、内置构造函数
基本数据类型:
➢字符串、数值、布尔、undefined、null
引用类型:
➢其实字符串、数值、布尔、等基本类型也都有专门的构造函数,这些我们称为包装类型。
➢JS中几乎所有的数据都可以基于构成函数创建。
(1)Object(对象)
(1)对象方法Object.keys
作用:Object.keys 静态方法获取对象中所有属性(键)
➢返回的是一个数组
(2)对象方法Object.values
作用:Object.values 静态方法获取对象中所有属性值
➢返回的是一个数组
(3)对象方法Object. assign
作用:Object. assign 静态方法常用于对象拷贝
使用:经常使用的场景给对象添加属性
(2)Array(数组常见方法)
数组常见实例方法-核心方法:
forEach、filter、map、reduce
数组常见方法-其他方法 :
- push() 在数组的末尾位置添加元素
- pop() 在数组的最后一个位置删除元素
- unshift() 在数组的第一个位置添加元素
- shift() 在数组的第一个位置删除元素
- sort() 以ASSIC码排序数组元素
- reverse() 倒序数组
- slice(start,end) 截取数组,不包括结束下标的元素
- splice() 删除数组中指定位置的元素
- join() 分割数组并转变成字符串
- find() 找数组的元素,找到返回true,否则undefined
- findIndex() 找到返回下标,找不到返回-1
- indexOf() 查找元素,找到返回下标,否则返回-1
- includes() 判断字符串是否包含指定的子字符串,返回true或者false
- map() 参数为回调函数,遍历返回新数组
- forEach() 遍历数组
- filter() 过滤方法
- every() 全部满足返回true
- some() 存在满足返回true
- lastIndexOf() 查找方法
- reduce() 参数为回调函数,四个参数(前一个,当前,下标,数组)
- reduceRight() 参数为回调函数
- concat() 合并数组
- Array.from() 伪数组转换为真数组
————————————————
原文链接:数组的常用方法总结22种_数组的所有方法总结-CSDN博客
(3)String(字符串常见实例方法:)
常见实例方法:
- length 用来获取字符串的长度 (重点)
- split('分隔符'), 把字符串分割为数组 (重点)
- substring(需要截取第一个字符串的索引 [,结束的索引号 ]), 提取字符串中两个指定索引号之间的字符(两个索引不能为负值) (重点)
- startsWith (检测字符串 [, 检测位置索引号]) 检测是否以某字符开头 (重点)
- includes(搜索的字符串 [,检测位置索引]) 判断一个字符串是否包含在另一个字符串中,根据情况返回true或false (重点)
- trim(),移除字符串首位空格,经常在对input和textarea的值做判断时用到 (重点)
- toUpperCase(),把字符串转换成大写的。
- toLowerCase(),把字符串转换成小写的。
- indexOf(),检测是否包含某字符 ,返回指定字符创第一次出现的位置。
- lastIndexOf(),检测是否包含某字符,返回指定字符串最后一次出现的位置。
- endWith 检测是否以某字符结尾
- replace(),替换指定子串或者与正则表达式匹配的子串。
- match(),找到一个或者多个子串或者正则表达式的匹配。
- charAt(),返回指定索引的字符
- search(),检索指定子串或者与正则表达式匹配的值,返回的值是数字
- toString(),返回字符串对象,比如把数字转换成字符串对象。
- concat(),连接两个或多个字符串,返回连接后的新字符串
- slice(), 提取字符串中两个指定索引号之间的字符(索引可以为负值,-1就是倒数第二位)
———————————————
链接:JavaScript 28个常用字符串方法及使用技巧 - 掘金
3、原型
(1)原型对象
➢构造函数通过原型分配的函数是所有对象所 共享的。
➢ JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象
➢这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
➢我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。
➢构造函数和原型对象中的this 都指向 实例化的对象
给数组扩展求和方法:
(2)constructor 属性
➢每个原型对象里面都有个constructor 属性(constructor 构造函数)
➢作用:该属性指向该原型对象的构造函数
使用场景:
➢如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了,此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
➢指向该原型对象的构造函数
(3)对象原型
➢对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,所以我们对象可以使用构造函数 prototype
➢原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。
注意:
➢ __proto__ 是JS非标准属性
➢[[prototype]]和__proto__意义相同
➢用来表明当前实例对象指向哪个原型对象prototype
➢__proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数
(4)原型继承
➢继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助 原型对象 实现 继承 的特性
(5)原型链
➢基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链
原型链-查找规则
① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)
③ 如果还没有就查找原型对象的原型(Object的原型对象)
④ 依此类推一直找到 Object 为止(null)
⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
四、深浅拷贝
1、浅拷贝
常见方法:
1、拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象
2、拷贝数组:Array.prototype.concat() 或者 [...arr]
存在的问题:
➢浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会
直接赋值和浅拷贝有什么区别?
➢直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址
➢浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会
相互影响
浅拷贝怎么理解?
➢拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
➢如果属性值是引用数据类型则拷贝的是地址
2、深拷贝
常见方法:
1、通过递归实现深拷贝
2、lodash/cloneDeep
3、通过JSON.stringify()实现
(1)通过递归实现深拷贝
➢如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
➢简单理解:函数内部自己调用自己, 这个函数就是递归函数
➢递归函数的作用和循环效果类似
➢由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
利用递归函数实现 setTimeout 模拟 setInterval效果
(2)lodash/_.cloneDeep
➢js库lodash里面cloneDeep内部实现了深拷贝
(3)通过JSON.stringify()实现
五、异常处理
1、throw 抛异常
➢异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行
总结:
1. throw 抛出异常信息,程序也会终止执行
2. throw 后面跟的是错误提示信息
3. Error 对象配合 throw 使用,能够设置更详细的错误信息
2、try /catch 捕获异常
➢我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息) try 试试 catch 拦住 finally 最后
总结:
1. try...catch 用于捕获错误信息
2. 将预估可能发生错误的代码写在 try 代码段中
3. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息
4. finally 不管是否有错误,都会执行
3、debugger
➢我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息)
六、处理this
1、this指向
普通函数this指向
➢谁调用 this 的值指向谁
➢严格模式下指向 undefined
箭头函数this指向
➢事实上箭头函数中并不存在 this !
➢箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
➢箭头函数中的this引用的就是最近作用域中的this
➢向外层作用域中,一层一层查找this,直到有this的定义
2、改变this
(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 传递参数 aru1, aru2..形式 apply 必须数组形式[arg]
bind 不会调用函数, 可以改变函数内部this指向.
主要应用场景:
call 调用函数并且可以传递参数
apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向
七、性能优化
1、节流(throttle)
➢所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数
使用场景:轮播图点击效果 、 鼠标移动、页面尺寸缩放resize、滚动条滚动 就可以加节流
方法1:(自定义)
方法二:Lodash 库 实现节流
2、防抖 (debounce)
➢防抖所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间
开发使用场景:搜索框防抖
方法一:自定义
方法二:Lodash 库 实现防抖