JavaScript
一、什么是JavaScript
当下最流行的脚本语言,在世界上的所有浏览器中都有
js
的身影,是一门脚本语言,可以用于我们与web站点和web应用程序的交互,还可以用于后台服务器的编写,例如node.js
二、语法特点
基于对象和事件驱动的松散型,解释型语言
单线程异步
三、JavaScript作用
- 页面的交互效果
- 表单验证
- 游戏
- 后台:node.js
四、引入方式
- 引入外部js
<script src="js文件路径"></script>
- 内嵌式js
<script> js代码 </script>
- 重定向
<a href="js代码"></a>
五、调试工具
console.log("") //输出内容到控制台
document.write("") //输出0内容到页面
alert("") //带有提示信息的警示框
六、JavaScript组成部分
- ECMAScript:规定js语法
- BOM:浏览器对象模型(Browser Object Model)
- DOM:文档对象模型(Document Object Model)
ECMAScript
一、变量与数据类型
计算机的本质是在操作各种数据,所以提出了数据类型,将操作到的数据进行分类。为了能够方便重复使用同一个数据,通过变量将它保存下来。
1.变量
变量是存储数据的容器
- 变量的声明和赋值
在js中使用 var 关键字进行变量的声明
1.先声明再赋值
2.声明的同时进行赋值
3.一次性声明多个变量,再分别进行赋值
4.一次性声明多个变量的同时进行赋值
2.命名规范
1.必须以字母,下划线,美元符开头,其余部分可以是数字,字母,下划线,$
2.不可以使用关键字和保留字
3.命名要有意义(见名思意)
4.驼峰命名法
getElementByClassName(小驼峰命名法)
5.js自己的命名习惯 首字母大写:
Number,String,Object
6.严格区分大小写
3.数据类型
通过学习数据类型能够了解到计算机处理的js中的数据,也能清楚的知道变量可能会存储的数据。
根据数据在内存中的存储位置不同,分为初试数据类型和引用数据类型。
- 初始数据类型
这类型的数据存储在内存中的栈区
1.数值型
整型 浮点型 最值:Number.MAX_VALUE Number.MIN_VALUE 在js中,0可以作为除数,结果为infinity(无穷大) 科学计数法
2.字符串型
使用引号包裹,单双引号的功能相同,双引号内部不可以嵌套双引号,单引号也不可以。单双引号可以互相嵌套。
如果在字符串中需要使用单双引号,可以使用转义字符(\)将它转为普通字符。
3.布尔型
true false
在js中,除了空字符串,0,false,null,undefined,NaN为假,其余都为真
4.undefined 未定义
只声明未赋值,变量默认值为undefined
使用var声明变量,在访问变量之前,变量的值为undefined,这种叫做变量提升
函数没有返回值时,默认值为undefined
5.null
6.Symblo 独一无二的值
- 引用数据类型
这类型的数据存储在内存中的堆区
object function
二、运算符
1.算术运算符
+ - * / % ** ++ --
+的作用:1.用于正常的加法运算,会将非数值类型转为数值类型进行运算
2.用于拼接的字符串,任意数据类型与字符串相加的结果为拼接后的字符串
-,*,/,%:正常进行运算,会将非数值类型转为数值类型进行运算。如果能够转为数值型进行正常的运算,如果不能,结果则为NaN(Not a Number)
++,--:在前面先自增或自减,在后面先运算再自增或自减
2.赋值运算符
= += -= *= /= %= **=
3.关系运算符
> < >= <= == === != !==
比较规则:1.数值型与数值型比较,正常进行比较
2.数值型与其他数据类型进行比较,会将其他的数据类型转为数值型进行比较,如果无法转为数值型则为false
3.字符串与字符串比较,依次进行比较ASCII编码值,直到能够分出大小为止
4.逻辑运算符
与:&& //运算的最终结果:运算符两边的表达式哪一个可以决定它的真假,则最终结果为哪个。如果运算左侧表达式为假,那么不会去看右侧表达式的真假,最终结果为左侧表达式的值(短路原则)
或:|| //运算的最终结果:左右两侧有一个表达式结果为真则为真,如果结果都为假则为假。运算符两边的表达式哪一个可以决定它的真假,则最终结果为哪个。如果左侧表达式为真,不会去看右侧表达式,最终结果为左边的值(短路原则)。给函数参数设置默认值的时候会用到
非:! //原表达式为真,去反则为假,反之也成立。
5.一元运算符
new delete +(正) -(负)
6.三元运算符
表达式?表达式为真的返回值:表达式为假的返回值
7.特殊运算符
,:分隔符
():提升运算的优先级
三、流程控制
默认情况下代码会从上往下执行,当需要去根据不同的条件执行不同的代码的时候,需要使用流程控制
1.顺序结构
代码正常的执行顺序
2.分支结构
根据不同的条件去执行不同的代码
if分支
用于判断范围
应用:判断数字的奇偶性
1.确定100块能够买的单个商品的最大数量 2.通过循环将每种商品的数量进行确定 3.判断条件为商品的价格相加为100
单路分支:
if(条件){
// 满足条件执行的代码
};
双路分支:
if(条件){
// 满足条件执行的代码
}else{
// 不满足条件执行的代码
}
多路分支:
if(条件1){
// 条件1满足执行的代码
}else if(条件2){
// 不满足条件1,满足条件2执行的代码
}else if(条件3){
// 不满足条件1,不满足条件2,满足条件3执行的代码
}else{
// 条件都不满足执行的代码
}
嵌套分支:
if(条件1){
// 满足条件1执行的代码
if(条件2){
// 满足条件1和2执行的代码
if(条件3){
// 满足条件1,2,3执行的代码
}
}
}
switch分支
用于判断单个的值是否满足条件
应用:根据传入数值的不同显示不同的内容
switch(值){
case 条件1:满足条件1执行的代码;break;
case 条件2:满足条件2执行的代码;break;
case 条件3:满足条件3执行的代码;break;
case 条件4:满足条件4执行的代码;break;
default:不满足执行的代码;break;
}
3.循环结构
for循环
根据一定的条件反复的执行一段代码(在条件满足的情况下重复执行循环体)
应用:当需要重复多次的执行某一段代码的时候(数组的遍历,DOM元素的遍历,求1-100和,求1-100的偶 数,求100-999的水仙花数)
初始值,终止值,步进值
for(初始值;终止值;步进值){
// 循环体
}
while循环
在满足条件的情况下重复的执行某一段代码,如果没有终止循环的条件,那么会陷入死循环
应用:当只知道循环条件,不知道循环次数的时候使用
while
循环
do_while循环
在满足条件的情况下重复的执行某一段代码,如果没有终止循环的条件,那么会陷入死循环;但是会先执行循环体后判断条件
应用:当只知道循环条件,不知道循环次数的时候使用
do_while
循环
for循环和while循环的区别
1.
for
循环必须知道循环次数,while
循环不需要2.优先考虑使用
for
循环3.当可以明确的写出初始值,终止值,步进值的时候一定选择
for
循环
while和do_while的区别
1.
while
循环只要条件不满足就不会执行循环体;do_while
无论条件是否满足都会先执行一次循环体2.
while
循环先判断再执行循环体;do_while
循环先执行循环体再判断
四、数组
1.数组的定义
数组是存储大量的或者一系列相关数据的容器
2.数组的创建
- 隐式创建
var arr = [];
- 实例化构造函数
var myArr = new Array();
3.数组的赋值
- 创建数组之后通过下标的方式进行赋值,数组的下标从0开始
var arr = [];
arr[0] = 1;
arr[1] = 2;
- 在创建数组的同时进行赋值
var arr = [1,2,3,4,5];
var arr1 = new Array(1,2,3,4,5)
4.数组的访问
数组通过下标访问数组的元素,数组的下标从0开始
5.数组数据的更新修改
通过数组的下标对对应的数据进行更新
6.数组的长度
数组的长度是指数组中数据的个数
arr.length // 了解数组的长度能够帮我们及时获取数组中的数据的个数以及数组长度与数组下标的关系
// 数组下标中的最大值为数组的长度减1 arr.length-1
// 访问数组中的最后一个数据 arr[arr.length-1]
7.数组的遍历
通过循环将数组中下标为0到下标为length-1的每一个元素都拿出来,这个过程就是遍历
在数据操作中,一般不会操作整个数组,需要的是数组中对应的数据,所以要用数组的遍历
8.数组扩展
- ES6数组的解构赋值
将数组中的元素依次提取出来赋值给另一个数组中的变量,这个过程就是解构赋值
应用:1.给函数传递参数 2.接收函数返回值 3.不使用中间变量,将两个变量的值进行交换
五、函数
1.函数的定义
将一段具有特定功能的代码段封装起来的代码段,并且可以重复调用
一次声明,多次调用,代码更加简洁
2.函数的作用
- 能够对代码重复使用:定义一次代码,可以多次使用
- 能够给同一函数传递不同的参数,实现不同的效果
- 使程序更加简洁,逻辑性更强,方便维护
3.函数的用处
当我们遇到同一段代码在不同地方使用的时候,就可以将这段代码封装成函数
应用:轮播图中的默认轮播状态(从右往左),2048小游戏中的数字的运动方式
4.函数的声明
- 通过
function
关键字声明函数(具名函数)
function 函数名(参数){
// 函数体
}
- 通过字面量方式创建函数(匿名函数,但是函数被保存在一个变量上)
var fn = function(参数){
// 函数体
}
- 实例化构造函数创建函数
var fn = new Function(函数体)
5.函数的调用
- 使用
function
关键字声明的函数:函数名()
- 使用字面量创建的函数:
变量名()
- 使用实例化构造函数:
变量名()
- 函数自调用(只能调用一次,确定在页面加载完成之后只执行一次的代码使用函数自调用,否则尽量不要用)
// 函数自调用的三种方式:
(function(){})() !function(){}() (function(){}())
- 通过事件调用
<div onclick="fn()"></div>
function fn(){
alert("我是事件调用函数")
}
6.函数声明的注意事项
- 如果两个函数名相同,后面的函数会将前面的函数覆盖
function fn(){
console.log("我是前面的函数")
}
function fn(){
console.log("我是后面的函数")
}
fn() // 输出结果为:我是后面的函数
- 使用
function
声明的具名函数可以在声明前进行调用(前值调用),但是使用字面量形式的不可以在声明前调用,因为使用字面量的方式在声明之前调用,变量的值为undefined
,不是一个函数
fn() // 我是具名函数
function fn(){
console.log("我是具名函数")
}
fn1() // fn1 is not a function
var fn1 = function(){
console.log("我是字面量函数")
}
- 在不同的
<script></script>
块中声明函数,后面的script块可以访问前面的script块中的函数,但是前面的不可以访问后面的
<script>
function fn(){
console.log("我是前面的")
}
</script>
<script>
fn() // 我是前面的
</script>
<script>
fn() // fn is not defined会报错
</script>
<script>
function fn(){
console.log("我是前面的")
}
</script>
7.ES6箭头函数
箭头函数表达式的语法比普通函数表达式更简洁。
- 如果函数没有参数
() => 函数体
_ => 函数体
- 如果函数有参数
(参数1,参数2,参数3,...) => 函数体
- 如果函数体中只有一条执行语句,我们可以省略大括号
() => console.log("我是一条执行语句")
- 如果函数体有多条执行语句,必须添加大括号
() => {函数体}
8.函数的参数
可以动态的改变函数的变量的类型与值,实现不同的效果
应用场景:实现任意行,任意列的表格
9.参数的分类
- 形参:在函数声明时小括号内写入的参数叫做形参:用于接收函数调用时传入的实参
- 实参:函数调用的时候,小括号内写入的参数叫做实参
10.参数详解
- 参数的数据类型(参数可以是任意数据类型)
- 参数的个数
默认情况下形参和实参是一一对应的
当实参个数大于形参个数的时候,多余的实参可以在arguments对象中找到,也可以使用ES6中的扩展运算符
...
// 实参数量大于形参数量
// ...plus接受多余的实参
function fn(one,...plus){
console.log(one) // 输出结果为"我是1"
// 每个函数中都有一个arguments对象,用来保存所有的实参
console.log(arguments) // 输出为全部的实参,数据类型为类似数组的Object
console.log(plus) // 输出结果为多余的实参,数据类型为数组Array
}
fn("我是1","我是2","我是3")
当形参数量大于实参数量,多余的形参默认值为undefined
- 参数的默认值
当实参数量小于形参个数,会导致多余的形参是undefined,会让我们的计算或操作没有意义,所以在需要的时候给参数设置默认值
ES6新语法:在函数创建的时候就添加默认值
function fn(a,b="的朋友",c="的同事"){
console.log(a,b,c)
}
fn("我是你爸爸")
使用短路原则添加默认值,利用逻辑或的短路原则
11.函数的length属性
将返回没有指定默认值的参数个数,仅包括第一个具有默认值之前的参数个数。
12.函数的返回值
函数的运算结果一般会拿来做其他运算,所以需要将函数的运算结果作为函数的返回值
- 返回值的添加
在函数体中使用return语句添加返回值
- 返回值的作用
给函数一个返回值
终止并跳出当前函数
- 注意事项
1.返回值可以是任意数据类型
2.任何一个函数都有返回值,如果没有return语句,默认返回值为undefined
3.一个函数有且只有一个return语句会生效(一个函数只有一个返回值)
4.当有多个返回值的时候,如果使用逗号隔开,最终结果为最右边的值,原因是return赋值是从左往右,后面会将前面的覆盖
5.如果函数确定需要多个返回值,那么可以将所有的返回值放在一个数组中或者对象,将这个数组或对象作为函数的返回值
13.函数的重载
根据函数传入的实参的个数或者数据类型的不同实现不同的函数功能,叫做函数重载
Array和String属于js原生对象
六、内置顶层函数
- Number()
将任意数据类型转为数值型,如果转不成数值型,那么结果为NaN
数值型转为本身
数值型的字符串转为对应的数值型,空字符串转为0,其余字符串都为NaN
true转为1,false转为0,undefined转为NaN,null转为0
- parseInt()
将任意数据类型转为整形
1.如果一个字符串中只包含数字,转为十进制数
2.如果字符串开始有很多空格,那么会从第一个不为空格的位置开始转换,直到第一个不为数字的位置结束
3.如果字符串中第一个字符不是数字,那么会转为NaN
4.如果有两个参数,第一个表示的是要转换的数字,第二个表示的是几进制(当前数字是几进制的),结果是一个十进制的数字
5.会将无意义的前导0和后导0去掉
- parseFloat()
将任意数据类型转为浮点型(小数)
1.只识别一个小数点
2.如果转换的数据是有效的整数,那么会返回整数,不会返回浮点数
3.其余规则与parseInt()相同(进制除外)
- String()
将任意数据类型转为字符串型
1.如果是undefined,null转为“undefined”,“null”
2.如果是数值型,转为自身的字符串
3.如果是布尔值,转为自身的字符串
- Boolean()
除了空字符串,0,false,null,undefined,NaN为假false,其余都为真true
- isNaN()
判断一个数据能否转为数值型
如果能够转为数值型,那么转为false,如果不能转为数值型,那么转为true
- eval()
将一段字符串当成代码执行,在执行的时候需要将字符串先解析成代码再执行,会影响性能,在不必要的情况下不要使用,安全性能差
七、数据类型转化
1.强制类型转换
不论数据是什么类型的数据,都会转为相应的数据类型
详细的转换规则请看内置顶层函数部分
- Number()
- String()
- Boolean()
- parseInt()
- parseFloat()
2.隐式类型转换
在js中进行数据运算的时候,运算符两端的数据类型是任意的,而这种现象是因为js在进行运算的时候帮助我们进行了隐式的数据类型转换,这是js弱类型语言的体现
- 算术运算符:减,乘,除。运算的时候会将非数值类型转为数值型进行运算,此过程隐式的调用了Number()内置顶层函数,将非数值类型转为数值型;如果转换不成功,整个表达式的结果为NaN
- 算术运算符:加。如果与字符串相加,会返回拼接后的字符串,与非字符串相加,规则同上
- 关系运算符:除了字符串与字符串比较之外,在比较的时候会将非数值型转为数值型进行比较,隐式的调用Number()进行转换,如果转换不成功结果为false。字符串与字符串比较的时候比较的是每个字符的ASCII编码值
- 逻辑运算符:与或非会隐式的调用Boolean()函数对参与运算的表达式(数据)进行数据类型转换(布尔值)
- 语句中存在的数据类型转换:
if,while,do_while
和三元表达式中参与判断的数据都会隐式的调用Boolean()函数进行转换
以上所涉及到的数据类型转换都会按照相应的规则去转换,转换规则参照内置顶层函数
数据类型转换就是将参与运算的数据转为我们需要的数据类型
八、预解析和作用域
1.环境
运行环境是js中非常重要的概念,指的是js代码执行的区域或位置
- 宿主环境(类似于毒液,细菌等)
一般指的是js运行的平台或软件,一般是浏览器
- 执行环境
指的是变量或者函数有权访问数据的位置
全局环境:指的是整个页面
局部环境:一个函数就是一个环境
因为有这些环境的存在,所以在不同的环境中声明的变量或创建的函数就拥有不同的起作用的范围,这个就称之为作用域
2.作用域
一段js代码起作用的范围就是作用域
作用:可以帮助我们在声明变量或创建函数的时候确定它们起作用的范围,防止出现访问错误
- 变量的作用域
1.全局变量
在全局环境中声明的变量,拥有全局的作用域(使用var关键字或者不使用关键字声明的变量)
2.局部变量
在函数环境中声明的变量,拥有局部的作用域
优点:提高程序的逻辑性,安全性,减少变量命名的冲突
拥有全局变量或函数在页面的任意地方都可以访问,但是拥有局部作用域的变量或函数在函数外部不可以访问,如果确实需要访问到,可以使用闭包
使用var关键字声明的变量在声明之前就可以访问,叫做变量提升,这是预解析的现象,在ES6中使用let声明的变量不存在变量提升
3.作用域链
当访问一个函数或者变量的时候,js会为变量(函数)创建一个作用域链,规定了变量或函数访问的次序:从当前环境开始,一次到包含环境,直到全局环境
俗语:当访问变量时,会从当前环境中寻找变量,如果不存在,就会去高一级的环境中寻找,直到全局环境,如果都不存在一般会导致错误的发生
4.预解析
js的解析器在执行js代码之前会将变量和函数提前到当前作用域的顶部,再按照顺序执行
- 预解析的顺序
1.按照script代码块进行解析
2.按照环境进行解析
3.全局环境:页面打开就解析
4.函数环境:函数调用的时候解析
5.解析过程中遇到了var和function关键字,会将它们声明的内容提前解析到内存中
6.如果后面还有script块,继续按照上面的顺序进行解析
5.块级作用域
在ES6之前,作用域包括全局作用域和函数作用域,没有块级作用域的概念
ES6中新增了块级作用域的概念,块级作用域用{}包括,if和for中的{}都拥有块级作用域
ES6中的let,const都拥有块级作用域
九、函数高级
1.回调函数
定义:将一个函数的指针或者函数整体作为参数传给另一个函数,并在调用的时候,这个函数就叫回调函数
何时用:我们需要在一个功能结束之后在执行另一个功能,这个时候就可以使用回调函数
2.递归函数
在函数体内部调用函数本身,这就叫递归函数
应用:求数字的阶乘,对象的深拷贝
3.闭包函数
在函数体外部可以访问函数内部的变量,这个函数就叫闭包函数
用处:创建一些私有的变量或函数
十、数组对象
1.数组对象的属性
- length:数组中元素的个数
- constructor:返回对创建此对象的数组函数的引用
2.数组对象的方法
- arr.push()
向数组末尾添加元素,会修改原数组,返回值是修改后的length值
- arr.unshift()
向数组开头添加元素,会修改原数组,返回值是修改后的length值
- arr.pop()
删除数组中末尾元素,会修改原数组,返回值是被删除的元素,只能删除一个
- arr.shift()
删除数组中的第一个元素,会修改原数组,返回值是被删除的元素,只能删除一个
- arr.splice()
任意位置的删除或添加
arr.splice(位置,删除元素的个数,要追加的元素)
添加或删除包含对应的下标,只添加元素的时候,删除元素的个数要写为0,修改原数组
- arr.slice()
数组的截取
arr.slice(截取的起始下标,结束下标)
截取时,包含起始下标,不包括结束下标,不修改原数组,返回值是截取到的数组,参数可以是负数,负数表示倒数,只穿一个参数表示从起始下标到结束
- arr.join()
使用连字符将数组中的数据隔开,成为字符串,不修改原数组,返回值是拼接好的字符串
- arr.concat()
多个数组的连接,不修改原数组,返回值是拼接后的新数组
- arr.indexOf()
查找某个值在数组中第一次出现的下标,返回值是下标,没有找到则返回-1
- arr.lastIndexOf()
倒叙查找某个值在数组中第一次出现的位置
- arr.sort()
数组的排序,如果没有参数,则会按照ASCII进行排序,如果有参数,这个参数必须是函数(回调函数),这个回调函数有两个参数a和b,修改原数组,返回值为排序后的数组
回调函数中有return值,a-b表示升序,b-a代表降序
- arr.forEach()
遍历数组,接受一个回调函数,回调函数的第一个参数为值,第二个参数为值对应的下标
- arr.filter()
过滤筛选,返回值是筛选后的数组,不修改原数组
- arr.map()
映射,返回值是映射后的数组,不修改原数组
- arr.some()
用来判断,只要有一个回调函数的值为true,最终结果为true,不修改原数组
- arr.every()
用来判断,只要有一个回调函数返回值是false,最终结果是false,不修改原数组
- arr.includes()
用来检查数组中是否包含某元素,包含返回true,不包含返回false
- arr.reverse()
数组倒序,返回值为倒序的数组,会修改原数组
- Array.from()
将类数组对象和可遍历对象转为真正的数组,如果开始下标为1,那么转化后的数组的第一个数据为undefined
- Array.of()
将一组值,转换为数组。返回参数值组成的数组。如果没有参数,就返回一个空数组。
十一、字符串对象
1.字符串的属性
- length:字符串的长度
2.字符串的方法
- str.charAt()
返回下标为index的字符串
- str.charCodeAt()
根据下标返回下标对应的ASCII值
String.fromCharCode(97)
将ACSCII码转化成字符串,涉及到数字与字母之间的转化可以使用该方法
str.indexOf()
查找一个字符或者字符串在字符串中第一次出现的位置,未找到返回-1,返回值为对应的下标
str.lastIndexOf()
倒序查找一个字符或者字符串在字符串中第一次出现的位置,未找到返回-1
str.replace()
将指定的字符串替换,返回值为替换后的字符串,不修改原字符串
str.slice()
字符串截取,识别负数,截取包含起始下标,不包含结束下标,不修改原字符串,返回值是截取到的字符串
- str.substring()
字符串截取,功能和slice相同,不识别负数
- str.substr()
根据长度截取字符串,参数为起始下标,截取的长度
- str.split()
以某一字符串将目标字符串分割,返回值是分割后的字符串,不修改原字符串
str.toLowerCase()
将字符串中的字母转为小写
str.toUpperCase()
将字符串中的字母转为大写
str.trim()
将字符串中的左右两边的空格去掉,返回值是去掉空格后的字符串
- str.match()
在字符串中检索指定的值,或找到一个或多个正则表达式的匹配,返回值是检索的结果
- str.concat()
用来连接多个字符串,不会修改原字符串,返回值是拼接后的字符串
- str.padStart()
向字符串的开头或结尾添加字符,使之达到指定的长度,返回值是新的字符串
参数:第一个为长度,第二个为填充的元素
注意:不写第二个参数,会用空格进行填充;填充的字符串会自动重复的进行填充直到填充满;如果原字符串长度已经达到长度,则返回原数组