前言
JavaScript一种运行在客户端(浏览器)上的解释性弱语言,是前端的重中之重,在计算机刚刚兴起的那个时代,这个由十天仓促编成的语言发展到现在也是令人吹嘘。
基础语法
文件引用
在一个单独的js文件中也可以编写JavaScript代码,然后在HTML文件使用script标签进行引用以下为演示
main.html
<script src=”main.js”></script>
main.js
alert(“hello,world”)
注意:外部JavaScript会是代码更加有序,更易于复用,且没有了脚本的混合,HTML也会更加易读,是个好的习惯。
但是引用之后,script标签中间无需写代码,否则会被忽略
输出
使用JavaScript向页面输出一句话。
注意:如果输入的内容写的是标签,也会被解析成网页元素。
<script>
document.write("我是div标签")
document.write(“<h1>我是标题</h1>”)
</script>
结束符
作用:使用英文的“;”表示语句结束
实际情况:实际开发中,可写可不写,浏览器可以自动推断语句的结束位置
现状:在实际开发中,越来越多的人主张,书写JavaScript代码时省略结束符
约定:为了统一,结束符要么每句都写,要么每句的不写
所有直觉性的“当然应该加分号”都是保守的,未经深入思考的草率结论,所有Vue.js的代码全部不带分号。
——尤雨溪
即使语句末尾的分号不是必需的,也应该加上。记着加分号有助于防止省略造成的问题,比如可以避免输入内容不完整。此外,加分号也便于开发者通过删除空行来压缩代码(如果没有结尾的分号,只删除空行,则会导致语法错误)。加分号也有助于在某些情况下提升性能,因为解析器会尝试在合适的位置补上分号以纠正语法错误。
——《JavaScript高级程序设计》
文章来源地址https://www.toymoban.com/news/detail-856361.html
文章来源:https://www.toymoban.com/news/detail-856361.html
控制台输出
向控制台输出一句话
<script>
console.log("输出一条日志");//最常用
console.info("输出一条信息");
console.warn("输出一条警告");
console.error("输出一条错误");
</script>
输入
prompt语句
作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字
<script>
prompt(“请输入您的年龄:”)
</script>
弹出窗口输出
使用JavaScript向弹出窗口输出一句话,如下
<script>
alert("Hello,World!");
</script>
注释
单行注释://注释内容
多行注释:/*注释内容*/
单行注释:快捷键为ctrl+/
<script>
//这是注释内容
console.log(“hello,world”)
</script>
多行注释:其内容均会被注释,快捷键为shift+alt+a
<script>
/**
*这是注释内容
*/
console.log(“hello,world”)
</script>
字面量
在计算机科学中,字面量(literal)是在计算机中描述 事/物
比如:
我们的工资是: 1000 //此时1000就是 数字字面量
程序员 //字符串字面量
还有接下来要学习的 [] 数组字面量 {} 对象字面量 等等
变量
声明变量:
要想使用变量,首先需要创建变量(称之为声明变量或者定义变量)
语法:let 变量名
声明变量有两部分构成:声明关键字、变量名(标识)
let是声明关键词
上图的代码可以直接简化为:
let age = 18
alert(age)
声明多个变量(但是提倡声明变量时,一个一个变量声明,为了更好的可读性):
变量命名规则:
- 不能用关键字
- 只能使用下划线、字母、数组、$组成,且数字不能开头
- 字母严格区分大小写,如Age和age是不同的变量
规范(建议使用)
1、起名要有意义
2、遵守小驼峰命名法
第一个首字母小写,后面每个单词首字母大写。例:userNAme
因为按照惯例,ECMAscript标识符使用驼峰大小写形式,即第一个单词的首字母小写,后面每个单词的首字母大写。
这种写法并不是强制性的,但因为这种形式跟ECMAScript内置函数和对象的命名方式一致,所以算得上是最佳实践。
变量扩展:let和var区别:
在较旧的JavaScript,使用关键字var来声明变量,而不是let
var现在一般不再使用它,只是我们还能在老版程序中看到它。
let为了解决var的一些问题。
var声明:
- 可以先使用再声明(不合理)
不会报错,之后声明underfined,即声明变量中没有值
- var 声明过的变量可以重复声明(不合理)
- 比如变量提升、全局变量、没有块级作用域等等
数组
数组(Array)——一种将一组数据存储在单个变量名下的方式
语法:let arr = [ ]
JavaScript中数组的使用方法与其他语言的用法相一致。
操作数组:
修改语法:arr[下标] = 数值
增加语法:利用push向数组中添加元素(数据)
1、数组.push()方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度
2、arr.unshift(新增的内容)方法将一个或多个元素添加到数组的开头,并返回该数组的新长度
删除语法:
1、数组.pop()方法从数组中删除最后一个元素,并返回该元素的值
2、数组.splice()方法 删除指定元素,返回该元素的值
语法:arr.splice(start,deleteCount)
arr.splice(起始位置(下标),删除几个元素)
常量
使用const声明的变量称之为“常量”
使用场景:当某个变量永远不会改变的时候,就可以使用const来声明,而不是let。
其命名规范与变量一致。
注意:常量不允许重新赋值,并且声明的时候必须赋值(初始化)
即:不需要重新赋值的数据使用const
严格模式
ECMAScript增加了严格模式(strict mode)的概念。严格模式是一种不同的JavaScript解析和执行模型,ECMAScript 3 的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。要对整个脚本启动严格模式,在脚本开头加上这一行:
“use strict“;
它是一个预处理指令。任何支持的JavaScript引擎看到它都会切换到严格模式。选择这种语法形式的目的不破坏ECMAScript 3 语法。
也可以单独指定一个函数在严格模式下执行,只要把这个预处理指令放到函数体开头即可:
function doSomething(){
“use strict”;
//函数体
}
所以现代浏览器都支持严格模式
数据类型
JavaScript数据类型整体分为两大类:
基本数据类型
引用数据类型
其中基本数据类型一共有5种基本数据类型:
字符串型(string)
数字型(number)
布尔型(boolean)
undefined型(undefined)
null型(null)
引用数据类型
对象(object)
因为JavaScript是一门弱数据类型的计算机语言,所以其数据类型的定义没有java和C语言等强数据类型的计算机语言那么的规范
例如:
let num = “你好” //这里定义了一个num变量
num = 14 //直接修改,系统不会报错
但是在Java中:
int num = 14 //就是定义了一个数字类型的变量。无法修改
注意:NaN是一个计算错误。它是一个不正确的或者一个未定义的数学操作所得到的结果。
并且NaN是粘性的。任何对NaN的操作都会返回NaN
并且如果让NaN === NaN ,返回结果为false
字符串类型
通过单引号(’ ’)、双引号(“ ”)或反引号(`)包裹的数据都叫做字符串,单引号和双引号没有本质上的区别,推荐使用单引号。
注意事项:
console.log(11) //所打印的11是数字类型(偏蓝色)
console.log(`11`) //所打印的11是字符串类型(偏黑色)
模板字符串
使用场景:拼接字符串和变量
在没有模板字符串之前,要拼接字符串比较麻烦
语法:` `(反引号)
内容拼接变量时,用${ }包住变量
布尔类型(boolean)
表示肯定或否定时在计算机中对应的时布尔类型数据。
它有两个固定的值true和false,表示肯定的数据用true(真),表示否定的数据用false(假)
未定义类型(underdined)
未定义时比较特殊的类型,只有一个值underfined。
什么情况出现未定义类型?
只声明变量,不赋值的情况下,变量的默认值为underfined,一般很少【直接】为某个变量赋值为underfined。
使用场景:
我们开发中经常声明一个变量,等待传送过来的数据。
如果我们不知道这个数据是否传递过来,此时我们可以通过检测这个变量是不是underfined,就能判断用户是否有数据传递过来
空类型(null)
JavaScript中的null仅仅是一个代表“无“、”空“或”值未知“的特殊值
null和underfined的区别:
underfined表示没有赋值
null表示赋值了,但是内容为空
官方解释:把null作为尚未创建的对象(即:将来会有个变量里面存放的是一个对象,但是对象还没创建好,就先给个null)
typeof运算符
使用typeof操作符可以用来检查一个变量的数据类型
console.log(typeof 123);
console.log(typeof "Hello,World!");
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof null);
注意:JavaScript中的特殊的数字
number类型用来表示整数和浮点数,最常用的功能就是用来表示10进制的整数和浮点数。
number表示的数字大小是有限的,如果超过了范围,则会返回infinity
- 最大值:+1.7976931348623157e+308
- 最小值:-1.7976931348623157e+308
- 0以上的最小值:5e-324
即:infinity:正无穷
-infinity:负无穷
NaN:非法数字(Not A Number)
其他进制:
二进制:0b开头表示二进制,但是,并不是所有的浏览器都支持
八进制:0开头表示八进制
十六进制:0x开头表示十六进制
注意:使用typeof检查一个number类型的数据时(包括NaN和infinity),会返回“number”
语法进阶
类型转换
隐式转换
某些运算符被执行时,系统内部会自动将数据类型进行转换,这种转换称为隐式转换。
规则:+ 号两边只要一个是字符串,都会另外一个转成字符串
在实际运算中,除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
缺点:转换类型不明确,靠经验才能总结
小技巧:
+号可以在运算之外作为正号解析将字符串型转换成数字型
任何数据和字符串相加结果都是字符串
显式转换
编写程序时过度依靠系统内部的隐式转换时不严格的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。为了避免因隐式转换带来的问题,通常需要对数据进行显式转换。
转换为数据类型
Number(数据)
转成数字类型
如果字符串内容里有非数字,转换失败时结果为NaN(Not a Number)即不是一个数字
NaN也是number类型的数据,代表非数字
parseInt(数据)
只保留整数
parseFloat(数据)
可以保留小数
比较运算符
“==“比较运算符有隐式转换,把”2“转换为2,并且双引号只判断值
console.log(2 == “2”) //true
“===“全等,判断 值 和数据类型都一样才行 所以在JavaScript中”===“较为常用。
逻辑运算符
语句
if语句
if语句有三种使用:单分支、双分支、多分支
单分支使用语法:
括号内的条件为true时,进入大括号里执行代码
小括号内的结果若不是布尔类型时,会发生隐式转换为布尔类型
如果大括号只有一个语句,大括号可以省略……
利用三元运算符执行满足条件的语句
?与:配合使用
语法:
switch语句
找到跟小括号里面的数据全等的case值,并执行里面对应的代码
若没有全等 === 的则执行default里的代码
例:数据若跟值2全等,则执行代码2
注意:
1、switch case语句一般用于等值判断,不适合于区间判断
2、switch case语句一般需要配合break关键字使用 ,没有break会造成case穿透。
上图为经典的case穿透
while循环
循环三要素:循环的本质是以某个变量为起始值,然后不断产生变化量,慢慢靠近终止条件的过程。
所以,循环三要素如下:
- 变量起始值
- 终止条件(没有终止条件,循环就一直执行,会造成死循环)
- 变量变化量(用自增或自减)
for循环
for循环与while循环的区别
当如果明确了循环的次数的时候推荐使用for循环
等不明确循环的次数的时候推荐使用while循环
函数
函数命名规范
和变量命名基本一致
尽量小驼峰命名法
前缀应该为动词
函数传参:
function 函数名(参数列表){
函数体}
当实参多于形参的时候,多出的实参无效
当形参少于实参的时候,函数会自动填上underfined
函数返回值“
函数是被设计为执行特定任务的代码块,在执行完特定任务之后,把任务的结果给我们。
缺点:把计算后的结果处理方式写死了,内部处理了。
解决:把处理结果返回给调用者
有返回值(return)的函数
当调用某个函数后,这个函数会返回一个结果出来,如果return后面不接数据或者函数内不写return,函数的返回值是underfined
匿名函数
没有名字的函数,无法直接使用。
使用方式:1、函数表达式2、直接执行函数
函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用,我们将这个称为函数表达式
实例如下:
与具名函数的区别在于具名函数可以在任意位置调用,但是函数表达式必须先声明后调用。
立即执行函数:
场景:为了避免全局变量之间的污染
语法:必须加分号
对象
对象(object):JavaScript里面的一种数据类型
可以理解为一种无序的数据集合,注意数组是有序的数据集合
用来描述某个事物,例如描述一个人
人有姓名、年龄、性别等等信息,还有吃饭睡觉打代码等功能
如果用多个变量保存则比较分散,用对象比较统一
对象使用
属性:信息或者叫特征(名词)。比如 手机尺寸、颜色、重量等等
方法:功能或叫行为(动词)。比如 手机打电话、发短信、玩游戏
属性:数据描述性的信息称之为属性,如人的性命、身高、年龄、性别等,一般是名词性的。
属性都是成对出现的,包括属性名和值,它们之间使用英文“:“分隔
多个属性之间使用英文,分隔
属性就是依附在对象上的变量(外面是变量,对象内是属性)
属性名可以使用双引号(“ “)或单引号(’ ’),一般情况下省略,除非名称遇到特殊符号如空格、中横线等等
增删改查:
1、查:声明对象,并添加了若干属性后,可以使用 . 获得对象中属性对应的值,pink老师称之为属性访问。
(1)语法:对象名.属性
(2)语法:对象名[‘属性’]
2、改与增:语法为对象名 .属性 = 新值
对象中的方法:数据行为性的信息
- 方法是由方法名和函数两部分构成,它们之间使用“ :“分隔
- 多个属性之间使用英文,分隔
- 方法是依附在对象中的函数
- 方法名可以使用“ “或‘ ’,一般情况下省略,除非名称遇到特殊符号如空格、下划线、中横线等等
遍历对象
为什么在以上案例中不能使用“obj.k“?因为在遍历时,将‘uname’、‘age’存入变量k中,注意存入变量k中的键是带有单引号的,obj.k就相当是obj.’uname’,所以会报错。要使用obj[k]
Web API
声明变量:var(不考虑)、let和const
const优先,尽量使用const,原因如下:
- const语义化更好
- 很多变量我们声明的时候就知道他不会被更改了,那为什么不用const
- 实际开发中,比如react框架,基本使用const
而且:有了变量先给const,如果发现它后面是要被修改的,再改为let
作用与分类
作用:就是使用js去操作html和浏览器
分类:DOM(文档对象模型)、BOM(浏览器对象模型)
WebAPIs:是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
DOM(Document Object Model——文档对象模型)是用来呈现以及与任意HTML或XML文档交互的API。即:DOM是浏览器提供的一套专门用来操作网页内容的功能。
DOM树:将文档以树状结构直观的表现出来,我们称之为文档树或者DOM树。下面是具体解释DOM中的一些基本的名词。
文档(document):一个页面就是一个文档。
元素(element):页面中的所有标签都是元素。
节点(node):页面中所有的内容在文档树中都是节点(如元素节点,文本节点,注释节点等等)。在DOM中,所有的节点都会被看作是对象,这些对象拥有自己的属性和方法。
并且,元素是节点的一种类型,所有的元素都是节点,但节点不一定是元素
描述网页内容关系的名词
作用:文档树直观的体现了标签与标签之间的关系
DOM对象:浏览器根据html标签生成的js对象
所有的标签属性都可以在这个对象上面找到
修改这个对象的属性会自动映射到标签身上
在HTML中,div是一个标签,但在js里面,div以及所有引进进去的标签都是对象。
展开后可以发现div对象里面有很多的属性。
所以:DOM的核心就是把内容当对象来处理的
document是什么?
是DOM里提供的一个对象,网页所有内容都在document里面。
获取DOM标签
一、通过CSS选择器获取
1、选择匹配的第一个元素
语法:
参数:包含一个或多个有效的CSS选择器 字符串
返回值:CSS选择器匹配的第一个元素,一个HTMLElement对象。
CSS选择器外必须加引号
2、选择匹配的多个元素
语法:
参数:包含一个或多个有效的CSS选择器 字符串
返回值:CSS选择器匹配的NodeList 对象集合
例如:
但是通过CSS选择器得到的是一个伪数组:
有长度有索引号的数组
但是没有pop() push()等数组方法
想要得到里面的每一个对象,则需要遍历(for)的方式获得
注意:哪怕只要一个元素,通过querySelectAll()获取过来的也是一个伪数组,里面只要一个元素而已。
3、其他获取DOM元素方法(了解)
操作元素内容
目标:能够修改元素的文本更好内容
DOM对象都是根据标签生生成的,所以操作标签,本质上就是操作DOM对象。
类名需要加点
方法:1、元素.innerText属性
将文本内容添加/更新任意标签位置
显示纯文本,不解析标签
2、元素.innerHTML属性
将文本内容添加/更新到任意标签位置
会解析标签,多标签建议使用模板字符
操作元素属性
1、操作元素常用属性
还可以通过js设置/修改标签元素属性,比如通过src更换 图片
最常见的属性比如:href、title、src等等
语法:
2、操作元素样式属性
(1)通过style属性操作CSS
语法:
举例:
注意:1、修改样式通过style属性引出
2、如果属性有-连接符,需要转换为小驼峰命名法,否则-连接符会被识别为减号
3、赋值的时候,需要的时候不要忘记加CSS单位
并且,因为这种方法是通过style行内样式控制元素样式,所以权重较高。
(2)操作类名(className)操作CSS
如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于CSS类名的形式。
语法:
注意:由于class是关键字,所以使用className去代替
className是使用新值换旧值,如果需要添加一个类,需要保留之前的类名。
(3)通过classList操作类控制CSS(经常使用)
为了解决className容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
语法:
类名不需要加点
重点提一下toggle,toggle会判断是否含有该类名,如果有就删掉,没有就加上。
操作attribute属性
attribute属性也是一个统称,它是指HTML标签的属性,在程序中对attribute属性的操作会直接反映到HTML标签中。attribute属性不仅可以操作元素的内置属性,还可以操作元素的自定义属性。
语法格式如下:
element.setAttribute(‘属性’,‘值’)
案例如下:
attribute还可以获取到自定义属性。
语法格式为:element.getAttribute(‘属性’);
移除属性:
通过元素对象的removeAttribute方法可以移除属性
语法格式为:element.removeAttribute(‘属性’)
操作表单元素属性
表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框。
获取:DOM对象.属性名
设置:DOM对象.属性名 = 新值
注意:inner 是双标签之间的空间 value 只存在于input单标签,在这里innerHTML是拿不到内容的,要用value
表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 。如果为true 代表添加了该属性 如果是false代表移除了该属性。
比如:disabled、checked、selected
自定义属性
标准属性:标签天生自带的属性,比如class 、id、title等等,可以直接使用点语法操作比如:disabled、checked、selected
自定义属性:在html5中推出来的专门的data-自定义属性
在标签上一律以data-开头
在DOM对象上一律以dataset对象方式获取
定时器-间歇函数
目标:能够使用定时器函数重复执行代码
定时器函数(setInterval)可以开启和关闭定时器
在指定的时间间隔内重复执行,根据时间间隔执行,不清除则永远重复执行。
1、开始定时器
作用:每隔一段时间调用这个函数,间隔时间单位是毫秒
注:一秒等于1000毫秒
例如:
- 函数名字不需要加括号
- 定时器返回的是一个id数字
关闭定时器:
必须赋值,使用let的原因是后面可能会变化
定时器的累加效果
box.onmouseover = function () {
timer=setInterval(function () {
height+=1;
console.log(height);
},1000)
};
导致最后打印的速度“越来越快“
原理:每停留在box上一次,就会产生一个定时器去执行height+1这个程序。
只有一个定时器:每隔1秒打印一次height。
第二次停留时,有两个定时器:每隔1秒有两个定时器去做这件事
简单的例子:
你点击一次按钮,相当于叫一个人过去,每隔1秒把打印一下;你点两次,就相当于让两个人去干同样的事情,都是每隔1秒打印一次,但是,假设过了1秒,第一个人过去打印了,第二个人也会过去打印,但是他们都是在同时进行的,会有叠加,就相当于每隔1秒打印多于原来两倍的速度。
累加问题的解决:先清除、后累加。先清除之前的定时器,然后再添加定时器
box.onmouseover = function () {
clearInterval(timer);
/*先清除后设置*/
timer=setInterval(function () {
height+=1;
console.log(height);
},1000)
};
-
事件监听
发展史:
DOM L0 : 是DOM的发展的第一个版本;L : level
DOM L1 :DOM级别1于1998年10月1日成为W3C推荐标准
DOM L2 :使用addEventListener注册事件
DOM L3 : DOM级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型。
目标:能够给DOM元素添加事件监听
什么是事件?
事件是在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮
什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称之为 绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等。
语法:
事件监听三要素:
事件源:那个DOM元素被事件触发了,要获取DOM元素
事件类型:用什么方式触发,比如鼠标点击click、鼠标经过mouseover等
事件调用的函数:要做什么事
举例说明:
注意:1、事件类型要加引号
2、函数是点击之后再去执行,每次点击都会执行一次
事件类型
鼠标事件
click 鼠标点击
mouseenter 鼠标经过(示例如下:)
mouseleave 鼠标离开()
焦点事件(表单获得光标):
focus 获得焦点
bius 失去焦点
键盘事件(键盘触发):
Keydown 键盘按下触发
Keyup 键盘抬起触发
文本事件(表单输入触发):
input 用户输入事件
事件对象
事件对象里面有事件触发时的相关信息
使用场景:
可以判断用户按下哪个键,比如按下回车键可以发布新闻
可以判断鼠标点击了哪个元素,从而做相应的操作
语法:
在事件绑定的回调函数的第一个参数就是事件对象
一般命名为event、ev、e
部分常用属性
type:获取当前的事件类型
clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置
offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置
key:用户按下的键盘键的值
环境对象(this)
指的是函数内部特殊的变量this,它代表着当前函数运行时所处的环境
并且每个函数里面都有this环境对象,普通函数里面this指向的是window
this指向的粗略规则:谁调用函数,函数里面的this就是谁
回调函数
如果将函数A作为参数来传递给另外一个函数的时候,这个函数就是回调函数。
DOM事件流
事件流指的是事件完整执行过程中的流动路径
事件流分为事件捕获和事件冒泡,事件捕获指的是事件流传播的顺序应该是从DOM树的根节点一直到发生事件的节点;事件冒泡是指事件流从发生事件的节点到DOM树的根节点。
事件捕获代码:
addEvenListenter第三个参数传入true代表是捕获阶段触发(很少使用)
若传入false代表冒泡阶段触发,默认就是false
并且若是用L0事件(onclick)监听,则只有冒泡阶段,没有捕获
阻止事件冒泡:
因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
语法:
注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。
示例:
解绑事件
L0语法,移除事件属性方式注册的事件,格式如下:
对象.onclick = null;
移除事件监听方式注册的事件,语法格式如下:
对象.detaEvent(type,callback);
对象.removeEventListener(type,callback);
事件委托
事件委托(事件代理)也是如此,其原理是将子节点对应的事件注册給父节点,然后利用事件冒泡的原理影响到每个子节点。当子节点触发事件时,会执行注册在父节点上的事件
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点
示例如下:
阻止默认行为
在HTML中,有些元素自身拥有一些默认行为。例如,使用<a>标签创建的超链接被单击后,浏览器会自动跳转到href属性设置的URL地址;点击表单的提交(submit)按钮后,浏览器会自动将表单提交。但是当表单信息有误的时候,我们将阻止这种默认行为的发生。
其他事件
页面加载事件
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
使用场景:
有时我们需要等页面资源全部处理完了做一些事情
load事件:监听整个页面资源给window加
DOMContentLoaded事件:
给document加
无需等待样式表、图像等完全加载
元素滚动事件:
滚动条在滚动的时候持续触发
事件名:srcoll
监听整个页面滚动:
当需要监视滚动了多少像素的时候,就需要用到scrollTop方法。
案例:让用户下拉到指定的像素时,显示左横栏。
页面滚动事件-滚动到指定的坐标
scrollTo()方法可把内容滚动到指定的坐标
语法:元素.scroolTo(x,y)
页面尺寸事件
会在窗口尺寸改变的时候触发事件:resize
检测屏幕宽度
获取元素宽高
1、获取宽高:
获取元素的可见部分宽高(不包含边框,margin,滚动条等)
clientWidth和clientHeight
2、获取元素宽高
offsetWidth和offsetHeight
获取元素的自身宽高、包含元素自身设置的宽高、padding、border
获取出来的是数值,方便计算
注意:获取的是可视宽高,如果盒子是隐藏的,获取的结果是0
获取位置:获取元素距离自己定位父级元素的左、上距离
offsetLeft和offsetTop注意是只读属性
总结:
节点
网页中的所有内容在文档树中都是节点,即元素、属性、文本等都属于节点,当利用DOM进行网页开发时,通过节点操作可以更加灵活地实现网页中的交互效果。
节点又三个常用属性:nodeName(节点名称)、nodeValue(节点值)、nodeType(节点类型)
nodeName:用于获取节点名称,返回全大写形式,如<div>返回的是DIV
nodeValue:用于获取节点值,一般适用于文本、注释类型的节点。
nodeType:用于获取数字表示的节点类型,如1表示元素节点。节点类型有很多种,常见的如上图红色所示。
节点操作
获取父节点的方法为使用parentNode属性获取当前节点的父节点,如果当前节点没有父节点,parentNode属性会返回null。通过parentNode获取父节点的语法如下:
node.parentNode
获取子节点
获取兄弟节点
可以使用previousSibling属性和nextSibling属性获取当前节点的上一个兄弟节点和下一个兄弟节点,进而获取到元素节点、文本节点等内容。
若没有兄弟节点,就返回null
如果想要获得兄弟元素节点,则可以返回使用nextElementSibiling,属性返回当前元素的下一个兄弟元素节点,使用previousElementSibLing属性返回当前元素的上一个兄弟元素。则返回null。
创建并添加节点
创建节点:
使用document对象的createElement()方法可以创建元素节点,因为该方法创建的节点是页面中原本不存在的,所有也被称为动态节点。
createElement()在使用时,只需将标签名作为参数传入即可,语法结构如下:
document.createElement(‘div’);
const div = document.createElement(‘div’);
console.log(div); //结果为<div></div>
添加节点:
节点创建后,我们需要根据实际的开发需求将节点添加到文档中的指定位置。DOM中提供了appendChild()方法和insertBefore()方法用于添加节点。
父元素.appendChild(插入的元素)//插在父元素的最后一个子元素后面
父元素.insertBefore()方法示例如下:
在特殊情况下,我们新增节点,按照如下操作:
复制一个原有的节点
把复制的节点放入到指定的元素内部
克隆节点:
cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
若为true,则代表克隆时会包含后代节点一起克隆
若为false,则代表克隆时不包含后代节点;默认为false
移除节点:
在DOM中,可以通过removeChild()方法将一个父节点的指定子节点移除,语法如下:
注:如不存在父子关系则删除不成功
删除节点和隐藏节点(display:none)有区别的:隐藏节点还是存在的,但是删除,则从html中删除节点。
M端事件:
移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。
触屏事件touch(也称触摸事情),Android和IOS都有。
touch对象代表一个触摸点。触摸点可能时一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
常见的触屏事件如下:
BOM
浏览器对象模型(Browser Object Model,BOM)是浏览器提供的用于JavaScript于浏览器窗口进行交互的一系列对象。在BOM中,顶级对象是window,表示浏览器窗口,其他对象都是window对象的属性。BOM没有统一的标准,每个浏览器都有自己对BOM的实现方法,因此BOM的兼容性较差。
延时函数:
setTimeout(函数,要延迟的时间)
setTimeout仅仅只执行一次,所以可以理解为就是把一段代码延迟执行。
清除延时函数
JS执行机制
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
这是因为JavaScript这门脚本语言诞生的使命所致——JavaScript时为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Wprker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
他们的本质区别:这条流水线上各个流程的执行顺序不同。
同步任务
同步任务都在主线程上执行,形成一个执行栈。
异步任务
JS的异步是通过回调函数实现的。
一般而言,异步任务有以下三种类型:
- 普通事件,如click、resize等等
- 资源加载,如load、error等等
- 定时器,包括setInterval、setTimeout等等
异步任务相关添加到任务队列中(任务队列也称为消息队列)
执行机制:
- 先执行执行栈中的同步任务。
- 异步任务放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取renw1队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
由于主线程不断的重复获得任务、执行任务、在获取任务、再执行,所以这种机制被称为事件循环(event loop)
BOM对象
window对象
location 的数据类型是对象,他拆分并保存了URL地址的各个组成部分
常用属性和方法:
href属性获取完整的URL地址,对其赋值时用于地址的跳转
hash属性获取地址中的哈希值,符号#后面部分
console.log(location.hash)
reload方法用来刷新当前页面,传入参数true时表示强制刷新
navigator对象
该对象主要记录了浏览器自身的相关信息
history对象
主要管理历史记录,该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
JS高阶方法
本地存储
随着互联网的快速发展,基于网页的应用越来越普通,同时也变的越来越复杂,为了满足各种各样的需求。会经常在本地存储大量的数据,HTML5规范提出了相关解决方案
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大、sessionStorage和localstorage约5M左右
常见的使用场景:
页面刷新的时候数据不刷新
localStorage
作用:可以将数据永远存储在本地(用户的电脑),除非手动删除,否则关闭页面也会存在
特性:可以多窗口(页面)共享(同一浏览器可以共享)
以键值对的形式存储使用
存储方式:localStorage.setItem(“键”,“值”)
本地存储只能存储字符串数据类型
sessionStorage
特性:生命周期为关闭浏览器窗口
在同一个窗口(页面下数据可以共享)
以键值对的形式存储使用
用法跟localStorage基本相同
复杂数据类型存储方法:
JSON.stringify(复杂数据类型)
正则表达式
正则表达式(Regular Expression)是用于匹配字符串中字符组合的模式。
在JavaScript中,正则表达式也是对象。
通常用来查找、替换那些符号正则表达式的文本,许多语言都支持正则表达式。
正则表达式在JavaScript中的使用场景:
例如验证表单:用户名表单只能输入英文字母、数字或者下划线,昵称输入框中可以输入中文(匹配)
过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等。
正则的使用:
- 定义规则
- 查找
定义正则表达式语法:
判断是否有符合规则的字符串:
test()方法,用来查看正则表达式与指定的字符串是否匹配
语法:
返回的是true,否则false
检索(查找)符合规则的字符串:
exec()方法在一个指定字符串中执行一个搜索匹配
语法:
返回的是数组,否则为null
元字符
普通字符:
大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。也就是说普通字符只能够匹配字符串中与它们相同的字符。
元字符(特殊字符)
是一些具有特殊含义的字符,可以极大提高灵活性和强大的匹配功能。
比如:规定用户只能输入英文26个英文字母,普通字符的话abcdefg……
但是换成元字符写法:[a-z]
分类:边界符、量词、字符类
边界符:正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
量词:表示重复次数
用来设定某个模式出现的次数
-
- 1.01 节 作用域
了解作用域对程序执行的影响及作用域链的查找机制,使用闭包函数创建隔离作用域避免全局变量污染。
作用域规定了变量能够被访问的“范围”,离开了这个范围,变量便不能被访问。
分为:局部作用域,全局作用域
函数作用域:
在函数内部声明的变量只能在函数内部被访问,外部无法直接访问
函数执行完毕后,变量实际是被回收了的。
块作用域:
在JavaScript中使用{}包裹的代码称之为代码块,代码块内部声明的变量外部将有可能无法被访问
- let声明的变量会产生块作用域,var不会产生块作用域
- const声明的常量也会产生块作用域
- 不同代码块直接的变量无法互相访问
- 推荐使用let或const
全局作用域:
<script>标签和.js文件的最外层就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。
全局作用域中声明的变量,任何其他作用域都可以被访问
函数中未使用任何关键字声明的变量为全局变量,尽可能少的声明全局变量,防止全局变量污染。
作用域链:
作用域链本质上是底层的变量查找机制。
在函数被执行时,会优先查找当前函数作用域中查找变量
如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域。
总结:1、嵌套关系的作用域串联起来形成了作用域链
2、相同作用域链中按着从小到大的规则查找变量
3、子作用域能够访问父作用域,父级作用域无法访问子级作用域
垃圾回收机制(GC)
js中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。
内存中的生命周期:
- 内存分配:当我们声明变量、函数、对象的时候,系统自动为他们分配内存
- 内存使用:即读写内存,也就是使用变量、函数等
- 内存使用:使用完毕,由垃圾回收器自动回收不再使用的内存
全局变量一般不会回收(关闭页面回收)
一般情况下局部变量的值,不用了,会被自动回收掉
内存泄漏:程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏。
堆栈空间分配区别:
- 栈(操作系统):由于操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面。
- 堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面。
引用计数法:
- 跟踪记录被引用的次数
- 如果被引用了一次,那么就记录次数1,多次引用会累加++
- 如果减少一个引用就减1 --
4、如果引用次数是0,则释放内存
致命问题:嵌套引用(循环引用)
如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会回收,导致内存泄漏。
因为他们的引用次数永远不会是0.这样的相互引用如果说很大量的存在就会导致大量的内存泄露
标记清除法:
现代浏览器已经不再使用引用引用计数算法了。通用的大多是基于标记清除算法的某些改进算法,总体思想都是一致的。
核心:1、标记清除算法将“不再使用的对象”定义为“无法达到的对象”
2、就是从根部(在js中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。
3、那些无法由根部出发触及的对象被标记为不再使用,稍后进行回收。
闭包
一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。
即:闭包 = 内层函数 + 外层函数的变量
闭包作用:封闭数据,提供操作,外部也可以访问函数内部的变量
闭包的基本格式:
闭包应用:实现数据的私有
比如,我们要做个统计函数调用次数,函数调用一次,就++
这样用于显示函数被调用的次数固然可以,但是coust是一个全局变量,很容易被修改。
变量提升
变量提升是JavaScript中只要var声明变量时才出现的现象,它允许变量声明之前即被访问。
函数提升:
函数提升与变量提升比较类似。
函数参数
- 动态参数:
argument是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。
argument时一个伪数组,只存在于函数中
argument的作用时动态获取函数的实参
可以通过for循环依次得到传递过来的实参
剩余参数:
剩余参数允许我们将一个不定数量的参数表示为一个数组
1、…是语法符号,置于最某函数形参之前,用于获取多余的实参
2、借助…获取的剩余实参,是个真数组
提倡使用剩余参数
展开运算符
展开运算符(…)将一个数组进行展开
典型运用场景:求数组最大值或者最小值、合并数组等
箭头函数
引入箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁。
箭头函数参数:
普通函数有argument参数,但箭头函数没有argument,可以使用剩余参数。
箭头函数的this指向
使用箭头函数前需要考虑函数中this的值,事件回调函数使用箭头函数,this为全局的window,因此,DOM事件回调函数为了简便,还是不太推荐使用箭头函数
-
- 1.02 节 解构赋值
解构形式如下图所示:
赋值运算符 = 左侧的[ ]用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量。变量的顺序对应数组单元值的位置依次进行赋值操作。
对象解构
- 基本语法:
赋值运算符“=”左侧的“{ }”用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
对象属性的值将被赋值给与属性名相同的变量
注意解构的变量名不要和外面的变量名冲突,否则会保错。
对象中找不到与变量名一致的属性是变量值为underfined
给新的变量名赋值:
可以从一个对象中提取变量并同时修改新的变量名
数组对象解构
forEach函数遍历:
forEach方法用于调用数组的每个元素,并将元素传递给回调函数
注意:forEach主要是遍历数组
参数当前数组元素是必须要写的,索引号可选。
filter方法
filter()方法创建一个新的数组,新数组中的元素是通过检查数组中符合条件的所有元素。
主要使用场景:筛选数组符合条件的元素,并返回筛选之后元素的新数组。
基本语法
例如:
返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组。
参数:currentValue必须写,index可选
因为返回新数组,所以不会影响原数组
创建对象
利用对象字面量创建对象:
利用new Object创建对象
利用构造函数创建对象:
构造函数:一种特殊的函数,主要用来初始化对象
使用场景:常规的{…}语法允许创建一个对象/。
创建构造函数的语法:大写字母开头的函数
说明:
- 使用new关键字调用函数的行为被称为实例化
- 实例化构造函数时没有参数时可以省略()
- 构造函数内部无需写return,返回值即为新创建的对象
- 构造函数内部的return返回值无效,所以不要写return
- new Object() new Date()也是实例化构造函数
实例成员
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
静态成员:
构造函数的属性和方法被称为静态成员(静态属性和静态方法)
总结:
常用静态方法
Object方法:
Object.key静态方法获取对象中所有属性(键),Object.values获取值
返回的都是一个数组
Object.assign()静态方法常用于对象拷贝
示例:
Array方法:
Array是内置的构造函数,用于创建数组
数组常见实例方法:
reduce返回累计处理的结果,经常用于求和等
基本语法:
arr.reduce(function(上一次值,当前值){ },初始值)
- 如果没有初始值,则上一次值以数组的第一个数组元素的值
- 每一次循环,把返回值给做为下一次循环的上一次值
- 如果有起始值,则起始值做为上一次值
其他方法:
find方法
返回第一个符合条件的对象
String方法
原型
构造函数通过原型分配的函数是所有对象所共享的,
JavaScript规定,每一个构造函数都会有一个prototype属性,指向另一个对象,所以我们也称为原型对象。
这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
我们可以把那些不变的方法,直接定义在prototype对象上,这样所以对象的实例就可以共享这些方法。
构造函数和原型对象中的this都指向实例化的对象
constructor属性
每个原型对象里面都有个constructor属性
作用:该属性指向该原型对象的构造函数
使用场景:如果用多个对象的方法,我们可以给原型对象采取对象形式赋值。但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象constructor就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数
对象原型
对象都会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototyte原型对象的属性和方法,就是因为对象有__proto__原型的存在。
到了这里,关于前端学习心得笔记之三(JavaScript篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!