什么是JS
JS最初是由网景公司创建的,参考了JAVA语言,主要是用来做前端校验的,后来被ECMA组织更名为ECMAScript(ES)。
JS的语法特点
1.js严格区分大小写;
2.每一行代码应该以分号结尾,但是可以省略;
3.js代码的执行顺序,从上往下依次执行。
JS的引入方式
1.行内式
通过on+事件名的形式书写js代码。
2.内部引入式
写在html中的script标签中。
3.外部js文件引入
通过src属性去指定js文件的路径。
JS的输入语句
通过promt函数,可以从浏览器中输入相应的数据到程序中。
JS输出语句
1.页面输出
document.write(123)
该方式输出的内容用户可见,会影响页面的整体内容。
2.弹窗输出
alert("hello world")
该方式输出的内容用户也是可见的,并且该方式具有一定的交互能力,会阻塞后面js代码的执行。
3.控制台输出
console.log("hello eorld!")
通过该方式输出数据用户不可见,也不会阻塞代码。
JS中的数据类型
Number、String、Boolean、Symbol、Null、Undefined、Object.
变量
变量是存储数据的容器,通过这个容器我们将程序中所用到的数据进行保存。
变量本质上是存放到内存空间中的,一旦程序结束,变量所占据的空间将得到释放。
在JS中创建并声明变量的方式
1.先声明,再赋值
var num
num = 10
console.log(num)
2.声明创建的同时进行赋值
var num = 10
console.log(10)
注意:如果只是声明了变量,但是没有对其进行赋值,不会报错,会打印undefined,
如果变量未声明就去访问,会报错“xxx is not defined”。
标识符
标识符:就是为变量、函数、形参、对象属性、对象方法等命名的一段字符。
标识符的命名规则
1.标识符只能由数字、字母、下划线、$组成;
2.不能以数字开头;
3.不能使用关键字或者保留字作为标识符的名字;
4.标识符的命名严格区分大小写;
5.标识符的命名应该遵循见名知义;
6.如果标识符由多个单词组成应采用驼峰命名法,如: abcAbcBcc。
typeof运算符
用于检测对应变量的类型。
用法:typeof+变量名
数据类型的相互转换
1.其他数据类型转换为Number类型
通过Number()、paserInt()、paserFloat()三种方法实现。
2.其他数据类型转换为String类型
通过String()、toString()两种方法实现。
3.其他类型转换为Boolean类型
通过Boolean()方法实现。
运算符
JS中的运算符包括:算数运算符、单目运算符、自增和自减运算符、赋值运算符、比较运算符、逻辑运算符、括号运算符、逗号运算符、条件运算符。
1、算数运算符
+(加)、-(减)、 * (乘)、\(除)、 %(模运算)
2.单目运算符
单目运算符是对一个数据进行运算的。
3.自增和自减运算符
前自加:
语法:++变量名 (变量名=变量名+1)
前自加是先将变量的值进行加1后,在参与后续的计算
后自加:
语法:变量名++(变量名=变量名+1)
先使用变量当前值参与运算,运算完毕后,再将变量的值进行加1
前自减:
语法:--变量名 (变量名=变量名-1)
前自减是先将变量的值进行减1后,在参与后续的计算
后自减:
语法:变量名--(变量名=变量名-1)
先使用变量当前值参与运算,运算完毕后,再将变量的值进行减1
4.赋值运算符
"=":将赋值号右边的值赋值给左边的变量
5.比较运算符
> < >= <= == !=
比较运算符是将左右两侧的表达式进行数据的比较,得到的一定是逻辑值(布尔值)
6.逻辑运算符
与(&&) 或(||) 非(!)
逻辑与(&&):一假即假,全真才真
逻辑或(||):一真即真,全假才假
逻辑非(!):true变false,false变true
7.括号运算符
括号运算符的优先级最高
8.逗号运算符
,表达式的值是将最后一个表达式的值作为整个逗号表达式的值返回
9.条件运算符
表达式1?表达式2:表达式3
计算过程,首先计算表达式1的逻辑值,如果为true 那么将表达式2的值作为整个条件表达式的值进行返回,反之则将表达式3的值作为整个条件表达式的值返回。
流程控制语句
流程控制语句包括:顺序结构、选择结构、循环结构。
1.顺序结构
顺序结构的执行顺序是从上往下依次执行的。
2.选择结构
1)单分支if
语法:
if(表达式){
语句1;
语句2;
......
}
执行流程:
执行到if语句时,先对括号中的表达进行判断,如果为true,执行if中的语句,如果为false,则不执行。
2)多分支if...else的嵌套
语法:
if(表达式){
语句,
...
}else if(表达式){
语句,
...
}else {
语句,
...
}
3)条件分支switch...case
语法:
switch(表达式){
case 表达式:
语句
case 表达式:
语句
...
default:
语句
}
执行流程:
首先计算switch后面表达式的值,将刚才计算的值与括号中每一个从上往下去进行匹配,匹配成功执行该代码块中的语句。
3.循环结构
1)while循环
语法:
while(表达式) {
语句;
...
}
执行流程:
首先计算while{}中表达式的值,如果为true,就执行{}中的循环体,反之不会执行循环体。
2)do...while循环
语法:
do {
代码块
}while(表达式)
执行流程:
直接先执行一次循环体的内容,执行完毕后再去判断while后的表达式的值,如果值为true则继续执行循环体,直到表达式为false退出循环;如果为false,直接结束循环,执行后续代码。
3)for循环
语法:
for(表达式1;表达式2;表达式3){
表达式4;
}
执行流程:
首先计算表达式1的值,对for循环进行循环变量的定义和初始化,接着计算表达式2的值,如果为true,执行循环体(表达式4),当循环体执行完毕,回到表达式3,循环执行,直到表达式2的值为false退出循环。
break和continue关键字
break:如果在循环中,执行break就会结束当前包含该break的循环,并且break后的语句将不再执行。
continue:在循环中执行continue就会跳过本次循环,直接进入下一次循环的判断,并且后面的语句将不再执行。
对象的创建
1.通过字面量直接创建一个对象
var person = {
name:'张三',
age:18
}
2.通过new构造函数创建一个空对象
var person = new Object()
对象中具体属性的访问
1.对象名.属性名
person.name
2.对象名[属性名]
person['name']
数组
js中由[]括起来的,用于存储有序的数据的一个数据结构,称作数组。
[]中可以同时存储多个不同类型的数据,多个数据之间使用逗号分割
数组的创建
1.通过字面量创建
var arr=[1,2,'q']
2.通过new 构造函数创建空数组
var arr = new Array()
数组的相关操作
1.访问数组中具体的某个元素的值
通过 数组名[下标值] 的方法,注意下标值是从0开始的
arr[1]
2.修改数组中的值
arr[0]=50
3.对数组添加新的元素
arr.push('d')
4.删除一个元素
arr.pop() 删除数组中最后一个元素,返回值是删除的元素
类数组
类数组:与真正的数组类型高度相似的一种假数组,类数组也是具备length属性和下标访问的,
不具备push和pop方法的。
函数
函数是指已经封装好了的可以重复调用,并且实现某种功能的代码块。
函数的创建和声明
无参函数:
function 函数名() {
函数体;
语句;
语句;
...
}
有参函数:
function 函数名(形参列表) {
函数体;
语句;
语句;
...
}
注意:函数声明创建后,并不会立即执行函数体的代码,函数只有被调用时才会在创建的位置和环境中执行代码。
函数的调用
语法:函数名()
函数的返回值
函数表达式默认的返回值是undefined,如果需要指定返回值,可以使用return语句将数据返回。
匿名函数的创建
语法:
var myfun = function(){
}
方法
函数也称作为方法,当函数作为某个对象的属性进行保存时,该函数就称为该对象上的一个方法。
例如:
var obj = {
name:'zs',
age:18,
sayHello:function(){
console.log()
}
}
此时的sayHello就被称作为方法。
函数的参数传递
函数的参数传递分为两种:值传递和引用地址传递。
1.值传递
当函数在调用时,实参数据是基本数据类型时,这时传递给形参的是值
当函数在运行中改变了形参变量是不会影响到实参变量的
2.引用地址传递
当函数在调用时,实参变量是引用数据类型时,这时传递给形参变量的就是地址值,共享一个空间
当函数在运行中改变了形参变量是会影响到实参变量的数据的
JS的预解析
在预解析过程中构建全局对象,并且寻找当前作用域下所声明的所有的var声明变量以及function声明的函数,将他们提前到当前作用域的开始。
如果var和function同时提前,函数优先。
arguments参数
用于接收函数调用时所传入的所有的实参,它是一个类数组,没有pop和push方法。
自执行函数
函数在被创建的同时就马上执行了,自执行函数通常情况下只会执行一次。
this关键字
this关键字:当函数被调用时,运行环境会自动向该函数隐式传入this对象。
1.当函数作为普通函数调用执行时,此时this执行的是window.
2.当函数作为某个对象的方法进行调用时,该方法中的this指向的是调用者,而非持有者。
3.构造函数时this指向的是一个新创建的{}对象
闭包
闭包就是当函数被嵌套声明时,并且该函数被直接或者间接返回或者赋值给某个全局变量,此时会形成一个闭包,在这个闭包它打包了该函数作用域链上的所有的变量以及函数。
构造函数
构造函数本质上是去实例一个对象,构造对象的
它的语法规则如下:
new 构造函数(形参列表)
此时new关键字做了如下事情:
1.在构造函数中创建一个空对象
2.让构造函数中的This指向这个空对象
3.进行对象的初始化
4.返回初始化后的对象
原型属性
每一个函数都具备prototype属性,每一个实例化对象都具备__proto__属性。
原型对象
存放在prototype属性或者__proto__属性中的对象,称作为原型对象。
原型链
js通过每个实例对象上的proto隐式原型属性,将原型对象进行连接,再通过原型对象的原型属性再进行连接,以此往复,直到最终的null,这样便形成了js中的原型链。
回调函数
将函数作为参数进行传递,传递到另一个函数中,传入的这个函数就成为回调函数。
回调函数的本质不是我们去调用,而是函数的内部或者某个条件达成了,自动调用的。
this劫持
this劫持就是强行的人为改变this的指向。
实现this的劫持三种方式(基于三个方法):apply call bind
1.apply
语法:函数表达式.apply(对象,形参数组)
2.call
语法:函数表达式.call(对象,形参1,形参2...)
3.bind
语法:函数表达式.bind(对象,形参1,形参2...)()
var&let&const三者的区别
var:
不存在块级作用域
可以进行变量声明的提升
可以改变值
不需要声明初始化(可以只声明,不赋值)
可以在同一个作用域下声明同名的变量
let:
存在块级作用域(全局作用域、函数作用域)
变量会进行提升,但是存在暂时性死区(隐式提升,提升之后不可以用,直到遇到真实定义的,中间这段是暂时性死区)
可以任意的改变值
不可以在同一个作用域下声明同名的变量或者同名的函数
不需要声明初始化(可以只声明,不赋值)
const:
具备块级作用域(全局作用域、函数作用域)
变量会进行提升,但是存在暂时性死区
声明的同时必须赋值
不可以在同一个作用域下声明同名的变量或者同名的函数
常量的值不能被改变
箭头函数
写法:
(形参列表)=>{
}
箭头函数通常是作为一种函数值,进行传递使用,它不能作为构造函数使用,不具备自己的this,不具备自己的名字。
当形参只有一个时,箭头函数的()可以省略,当箭头函数中的代码块语句只有一句时,{}可以省略,当只有一句,并且省略了{}时,箭头函数就会将这一句表达式所执行的结果作为返回值返回。
箭头函数的this指向的是该箭头函数被创建时,当时作用域下的this
rest参数
rest参数用来把实参传入的多余的数据,收集起来存放到数组中,它只能放到所有形参的末尾或者单独使用。
let fun(a,b,...c){
console.log(a,b,c)
}
fun(1,2,3,4,5)==>a=1,b=2,c={3,4,5}
扩展运算符
扩展运算符其实就是rest参数的反向操作
let arr=[1,2,3,4]
console.log(...arr) ==>1,2,3,4
模板字符串
使用``包裹起来的字符串,模板字符串中支持换行
console.log(`${str2},你好我是${str1}`)
String实例对象相关API
1.length属性
用于获取字符串的长度,可以通过字符串[索引值]访问字符串中对应的单个字符,但是不能通过这种方式进行修改。
2.charAt方法
从一个字符串中返回指定位置的字符
语法:str.charAt([index])
3.charCodeAt方法
从一个字符串中返回指定索引下对应字符的编码
4.indexOf方法
从当前字符串的指定位置查找第一个出现的特定的子串的位置索引,如果查找成功,则返回该子串字符的首字符索引下标,如果未查找成功则返回-1
语法:str.indexOf(searValue[,fromIndex])
注意:该方法是正向查找
5.lastIndexOf方法
从当前字符串的指定位置反向查找第一个出现的特定的子串的位置索引,如果查找成功,则返回该子串字符的首字符索引下标,如果未查找成功则返回-1
语法:str.lastIndexOf(searValue[,fromIndex])
注意,该方法是反向查找,但是索引还是从左往右数
6.includes方法
判断当前字符串中有没有指定的某个子串,如果有则返回true 没有则返回false
7.starsWith方法
判断当前字符串是否以某个指定字符串进行开头 根据情况返回true或者false
8.endWith方法
判断当前字符串是否以某个指定字符串进行结尾 根据情况返回true或者false
9.concat方法
将一个或多个字符串与现有的字符串进行拼接,形成一个新字符串返回
语法:str.concat(str)
10.split方法
使用指定的分隔符字符串,将一个string对象进行分割,形成一个字符串数组
注意:如果不传入指定的分隔符,那么则将原字符串一次性返回
11.slice方法
截取某个字符串中的一部分,并放回一个新的字符串,不会改变原字符串
slice方法有两个参数 1.开始下标 2.结束下标(默认就是截取到最后)
左闭右开的区间 [beginIndex,endIndex)
支持负的索引
12.subString方法
返回一个字符串在开始索引到结束索引之间的字符串
注意:不支持负数形式,如果为负数,无法进行截取,则返回完整的字符串
左闭右开区间
如果beginIndex小于endIndex两者进行交换
endIindex大于字符串长度,代表截取到末尾
13.toLowerCase方法
将大写字母转换成小写字母
14.toUpperCase方法
将小写字母转换成大写字母
15.trim 去除字符串前后两端的空白符
trimStart 去除开头空白符
trimEnd 去除结尾空白符
Array实例对象常用API
1.at方法
通过指定的数值去返回对应元素,支持负数
语法规则:at(index)
如果index是负值,那么则从当前元素的后面往前面计算
2.push方法
对当前数组末尾添加一个或多个新元素,该方法改变原数组
返回值是数组新的length值
3.pop方法
删除当前数组中的最后一个元素,并返回
4.unshift方法
对当前数组开始位置添加一个或多个元素,改变原数组
5.shift方法
删除当前数组的第一个元素并返回,修改原数组
6.reverse方法
将数组反序
7.sort方法
该方法是对数组中的元素进行排序,可接受参数,但是参数必须是函数(比较函数)
如果不传入比较函数,他会按照字符编码进行排序
8.concat方法
连接多个数组返回一个新数组
9.join方法
将数组中的元素进行合并,通过指定的分隔符,合并形成一个字符串返回
语法规则:join(str)
默认情况str为‘,’
10.splice方法
通过该方法可以删除指定元素,修改指定元素,添加指定元素,任意位置
语法规则:splice(index,hm,elmt1,elmt2...) 起始位置 要删几个元素
注意:如果省略hm(删除个数),将数组清空
返回值:被删除的元素数组,没有被删除的元素,返回空数组
11.forEach方法
语法规则:arr.forEach(callback(element,index,thisArg))
elment:代表当前数组中的元素
index:代表当前数组中元素的下标
thisArg:接收回调this, thisArg==>arr
回调函数,一般采用箭头函数的写法,但是也可以使用function函数
注意:被传入的回调函数,每访问一次数组中的元素就被执行一次
forEach方法返回值是undefined
forEach遍历数组整个过程不允许中断
12.map方法
语法:arr.map(callback(element,index,thisArg))
该方法会遍历每一个数组元素
每遍历一个元素都会调用一次回调函数,并且将该回调函数的返回值存放到新数组中,最终整体返回
13.filter方法
语法:arr.filter(callback(element,index,thisArg))
每访问一次元素都会调用一次回调函数,如果该回调函数的返回值是true,那么将当前访问的元素保存到一个新数组,最终作为结果返回。