JavaScript
JavaScript(JS)是一种脚本语言,可以用来更改页面内容,控制多媒体,制作图像动画等.
-
在body标签里面写一个script标签,在script标签里面编写JavaScript代码
-
或者在script标签定义一个src填写文件路径,重新创建一个js文件进行编写代码
-
/* 'use strict' 严格检查模式 */ /* 放在第一行 */
数据类型
基本类型
字符串
-
用单引号或者双引号包裹
-
js中也有转义字符
-
多行字符串,用反引号包裹的字符串可以多行编写
// 例 // 将超链接这个标签用字符串的四种方法包裹起来 <a href="1.html">超链接</a> let s1 = `<a href="1.html">超链接</a>`; //反引号 let s2 = "<a href="1.html">超链接</a>"; //双引号 let s3 = '<a href="1.html">超链接</a>'; //单引号 let s4 = "<a href=\"1.html\">超链接</a>"; //转义字符
模板字符串
-
拼接字符串
-
可以直接用${}这个替换加号
-
//例 //用模板字符串的拼接方式拼接URL请求参数,用户名和年龄不知 let name; let age; let url = "/test?name=${ name }&age=${ age };
常用API
-
//字符串长度 字符串名字.length 字符串名字[0] //大小写转换 //小写转大写 字符串名字.toUpperCase() //大写转小写 字符串名字.toLowerCase() // 截取字符串 字符串名字.substring(从哪开始,截取到哪) //包前不包后 字符串名字.substring(从哪开始) //截取到最后
整数和小数
-
number类型标识的是双精度浮点小数
-
可以除0
-
有运算精度问题
-
10 / 3 = 3.333333333333333333333333; 10 / 0 = infinity(正无穷大) 2.0 - 1.1 = 0.8999999999999999999999999
-
-
将字符串转为可以运算的number类型
-
parseInt(数字字符串)
-
parseInt("10.5") // 结果为10,但还是number类型
-
-
数字字符串-0
-
"10"-0 //结果为10
-
-
-
bigint为整数类型
-
直接在数字后面加上n即可
-
不可以除0
undefined和null
- 执行表达式或函数没有返回结果,出现undefined
- 访问数组不存在的元素,访问对象不存在的属性,出现undefined
- 定义变量,没有初始化,出现undefined
不同点
- undefined由JavaScript主动产生
- null由程序员自己产生
共同点
- 都没有属性和方法
- nullish
boolean
在js中,并不是boolean才能用于条件判断,你可以在if语句中使用[数字],[字符串]...作为判断条件
let a = 1;
if(a){
console.log("进入了");
}
需要条件判断时,这个值被当做true还是false,当做true的值归类为truthy,当做false的值归类为falsy
truthy
- 除了falsy以外绝大部分都是truthy
- {},[],"false"等等
falsy
- false
- nullish(null,undefined)
- 0,0n,NaN
- "空字符串",'空字符串',
空反引号
数组类型
基本使用
//定义
数据类型 数组名 = [值1,值2,值3];
//调用
数组名[索引] --索引从0开始
//修改
数组名[索引] = 修改后的值;
Array可以包含任意的数据类型
var arr = [1,'2',true]
常用API
-
length
-
// 数组长度 //使用 数组名.length //重新加入给数组赋值,数组大小就会发生变化,如果赋值过小,元素就会丢失
-
-
indexof
-
//通过元素获得下标索引 //使用 数组名.indexof(值)
-
-
slice
-
//截取数组一部分,返回一个新数组(类似substring) 旧数组名,slice(从哪截取,截取到哪) //包前不包尾 旧数组名.slice(从哪截取) //截取到最后一个
-
-
push和pop
-
/* 向数组的尾部追加(移除)一个元素 使用 */ 数组名.push(追加的元素); 数组名.pop(); //移除数组尾部的元素 // 例 let arr = [1,2,3]; arr.push(4); //1,2,3,4 arr.pop(); //1,2,3
-
-
shirt和unshirt
-
/* 移除(添加)数组头部的元素 使用 */ 数组名.shirt(); 数组名.unshirt(追加的元素); // 例 let arr = [1,2,3]; arr.shirt(); //2,3 arr.unshirt(1,3); //1,3,2,3
-
-
splice
-
/* 移除数组任意位置的元素 使用 */ 数组名.splice(从哪个索引开始删除,删除几个元素); //例 let arr = [1,2,3,4]; arr.splice(1,2); //1,4
-
-
join
-
/* 将字符串数组拼接为一个字符串 使用 */ 数组名.join(); //参数填分隔符 //例 let arr = ['我','是','靓','仔']; arr.join(''); //"我是靓仔"
-
-
map
-
// 将一个旧数组变为一个新数组 //例:将[1,2,3,4]变为[10,20,30,40]; //使用 let arr = [1,2,3,4]; //定义数组 arr.map( i=>return i*10) //参数为数组的变换规则 //传给map的函数,参数代表旧函数,返回值代表新元素
-
-
filter
-
// 可以过滤固定条件的值 //例:将取模不等于1的元素过滤掉 //使用 let arr = [1,2,3,4]; arr.filter( (i)=> i%1==1 ); //传给filter的函数,参数代表旧元素,返回值为true的表示要留下来的元素
-
-
foreach
-
// 遍历数组 //例:let arr = [1,2,3,4]; arr.foreach( (i)=>console.log(i) )
-
-
sort
-
//排序数组 数组名.sort()
-
-
reverse
-
//反转数组 数组名.reverse()
-
-
concat
-
//数组拼接元素 数组名.concat(新数组) //返回一个新数组,原数组不改变
-
对象类型
若干个键值对
-
定义
-
数据类型 对象名 = { 属性名: 属性值, 属性名: 属性值, 属性名: 属性值 } //例 var person = { name: "zhangsan", age: 18, gender: "男" } //{}表示一个对象,每个属性用逗号隔开,最后一个属性不用加逗号
-
-
赋值
-
对象名.属性值 //例 person.name = "lisi";
-
-
删除
-
delete 对象名.属性值 //例 delete person.name
-
-
判断属性值是否在这个对象中(包含继承)
-
'属性值' in 对象名 //例 'age' in person
-
对象中的每个键都是字符串类型
-
-
判断属性值是否在这个对象中(不包含继承)
-
对象名.hasownProperty('属性值') //例 person.hasownProperty('age')
-
变量和常量
let
-
let 变量名 = 值; //分号可加可不加 //例 let a = 5
-
let声明的变量可以多次赋值,例如
-
let a = 100; a = 5;
-
const
-
const 常量名 = 值; //分号可加可不加 //例 const a = 5
-
const修饰的常量只能被赋值一次
-
只能赋值一次不代表不能修改那个值,例如
-
const a = [1,2,3]; a[2] = 5;
-
var
-
var 变量名 = 值; //分号可加可不加 //例 var a = 5
-
var声明的变量可以多次赋值,例如
-
var a = 100; a = 5;
-
var和let的区别
如果函数外层引用的是let变量,name外层普通的{}(例如if的)也会作为作用域边界,最外层的let也占一个script作用域
运算符
基本运算符
- 加(+)
- 减(-)
- 乘(*)
- 除(/)
- 取余(%)
- 乘方(**)
赋值运算符
-
加等于(+=) 减等于(-=) 乘等于(*=) 除等于(/=) 取余等于(%=) 乘方取余(**=)*
自增减运算符
-
自增运算符(++) 自减运算符(--)
比较运算
-
等于(==) 不等于(!=) 大于(>) 大于等于(>=) 小于(<) 小于等于(<=)
严格运算符
-
严格相等运算符(===) 严格不等运算符(!==)
-
和==与!=的区别
-
1 = '1' //结果为true 1 === '1' //结果为false
-
typeof
-
查看某个值的类型
-
//定义 typeof 值;
-
逻辑运算符
-
//逻辑或(||) 值1 || 值2 //如果值1是truthy,返回值1,如果值1是falsy,返回值2 逻辑与(&&) 逻辑非(!) //把操作数的值转为布尔值,并取反
其他运算符
-
//空值合并操作符(??) 值1 ?? 值2 //如果值1不是null或undefined,返回值1,如果值1是null或undefined,返回值2
-
//可选链操作符(?.) obj?.prop //当obj为nullish时,短路并且返回undefined
-
展开运算符(...)
-
打散数组传递给多个参数
-
//定义 ...要打散的数组
-
需求:将数组中的1,2,3依次传给函数参数的ABC //定义需求 let arr = [1,2,3]; function test(a,b,c){ console.log(a,b,c); } //使用展开运算符 test(...arr); //...arr为打散arr数组
-
-
复制数组或对象
-
需求1:复制该数组 //定义需求 let arr1 = [1,2,3]; //复制数组 let aarr2 = [...arr1];
-
需求2:复制该对象 //定义需求 let obj1 = {name: "张三",age: 18}; //复制对象 let obj2 = {...obj1};
-
展开运算符复制属于浅拷贝,例
-
let o1 = {name: "张三",address: {city: "广东"}}; let o2 = {...o1};
-
此时修改o1中的city,o2也会跟着修改
-
-
合并数组或对象
-
需求:合并数组 //定义数组 let a1 = [1,2]; let a2 = [3,4]; //使用展开运算符合并数组 let b = [...a1,...a2]; //将两个数组都打散就可以合并为一个数组了 //还可以这样使用,在12和34中间插入一个5 let b = [...a1,5,...a2];
-
需求:合并对象 //定义对象 let o1 = {name: "张三"}; let o2 = {age: 18}; let o3 = {name: "李四"}; //合并对象 let o3 = {...o1,...o2}; //如果有重复的属性时,后面的会覆盖前面的 let o3 = {...o1,...o2,...o2}; //结果为李四,18
-
-
-
解构赋值
-
中括号操作符([])
-
需求:将数组中的值依次赋值给ABC //定义数组 let arr = [1,2,3]; //使用中括号操作符赋值给ABC let [a,b,c] = arr;
-
需求:将数组中的1,2,3依次传给函数参数的ABC //定义需求 let arr = [1,2,3]; //使用中括号操作符 function test([a,b,c]){ console.log(a,b,c); }
-
-
大括号操作符({})
-
需求:将对象中的值依次赋值给name,age,sex //定义需求 let obj = {name: "张三",age: 18,sex: "男"}; //使用大括号操作符赋值给ABC let {name,age,sex} = obj;
-
需求:将对象中的值依次传给函数参数的name,age,sex //定义需求 let obj = {name: "张三",age: 18,sex: "男"}; //使用中括号操作符 function test({name,age,sex}){ console.log({name,age,sex}); }
-
-
控制语句
- if...else
- switch
- while
- do.....while
- for
以上都跟java一样
for...in
-
主要用途:遍历对象
-
//创建对象 let father = {name: "张三",age: 18}; //遍历对象 for(const n in father){ //遍历father对象,遍历到的值赋值给n console.log(n); }
-
如果对象中有方法,方法名也会被遍历出来
-
遍历子对象时,父对象的属性也会遍历出来
-
如果想获取属性值,只能使用中括号操作符,不能使用展开操作符
-
//创建对象 let father = {name: "张三",age: 18}; --遍历对象并且获取属性值 for(const n in father){ console.log(n,father[n]); }
-
for of
-
主要用途:遍历数组,也可以是其他迭代对象,如map,set等
-
//遍历简单的数组 //创建数组 let a1 = [1,2,3]; //遍历数组 for(const n of a1){ //遍历a1数组,遍历到的值赋值给n console.log(n); }
-
//遍历对象数组 //创建数组 let a2 = [ {name: "张三",age: 18}, {name: "李四",age: 20}, {name: "王五",age: 22} ]; //遍历数组 for(const {name,age} of a2){ //遍历a2数组,遍历到的值赋值给n console.log(name,age); //获取属性值 }
try catch
-
用途:处理可能会出现的异常
-
try{ 可能会出现异常的代码体 }catch(e){ console.log("出现了异常",e.message); ---e.massage打印出现的异常 }finally{ 一定执行的代码块 }
集合
Map与Set
-
//创建 new Map(); //例 //存储姓名和年龄 var student = new Map([["张三",18],["李四",20]]); //获取张三的值 对象名.get("张三"); //添加一个新的值 对象名.set("王五",22);
-
无需不重复集合,会去重
函数
-
定义和调用
-
//定义方式1 function 函数名(参数...){ 函数体 } //定义方式2 数据类型 函数名 = function(参数...){ 函数体 } //调用 函数名(参数...)
-
-
例子
-
//定义 function add(a,b){ //不用写参数的类型 return a+b; } //调用 add(s,20);
-
对函数的参数没有限制
-
对函数参数的个数没有限制
- 可以0个参数,也可以多个参数
-
-
默认参数
-
function add(a = 20,b = 30){ console.log(a,b); } //如果调用函数时不给参数,则会使用默认参数 add() //结果就是20,30 //如果只给一个参数 add(10) //结果就是给值的那个用新给的值,没有给的值用默认参数 //只给后面的值 add(unfined,10) //此时第一个参数就会使用默认参数
-
匿名函数
-
定义和调用
-
//定义 (function (参数){ 函数体 }) //建议在最外边加上一个小括号 //使用场景1调用,只调用一次 (function (参数){ 函数体 })(参数) //使用场景2调用,作为其他对象的方法 document.getElementById("标签名字").onclick=(function(参数){ 函数体 })
-
例子
-
-
//定义 (function (a,b){ return a+b; }) //调用1 (function(a,b){ return a+b; })(5,7) //调用2 document.getElementById("p1").onclick=(function(){ console.log("鼠标单击了我....") })
箭头函数
-
定义和调用
-
//定义 (参数) =>{ 函数体 } //使用场景1调用,只调用一次 (参数) =>{ 函数体 }(参数) //使用场景2调用,作为其他对象的方法 document.getElementById("标签名字").onclick=(参数) => 函数体
-
-
例子
-
//定义 (a,b) =>{ return a+b; } //调用1 (a,b) =>{ return a+b; }(5,6) //调用2 document.getElementById("p1").onclick=() => console.log("鼠标单击了我....")
-
匿名函数和箭头函数用法大致相同,有些不一样
-
如果只有一个参数,{}可以省略
-
如果函数体内只有一行代码,{}可以省略
-
高阶函数
-
函数作为参数
-
function a(){ console.log("a"); } function b(fn){ console.log("b"); fn(); } b(a) //结果为b,a
-
-
函数作为方法返回值
-
function a(){ console.log("a"); function b(){ console.log("b"); } return b; } a()() //第一个()是调用a,第二个()是调用b
-
另外一个函数的返回值作为参数的函数称为高阶函数
-
两个函数a都称为高阶函数--还有数组中的map,filter,foreach
-
作为参数的称为回调函数
-
两个函数b都称为回调函数
-
作用域
-
以函数为分界线划定作用域,所有函数之外是全局作用域
-
查找变量时,由内向外查找
-
在内层作用域找到变量,就会停止查找,不会再找外层
-
所有作用域都找不到变量,报错
-
-
作用域本质上是函数对象的属性,可以通过console.dir来查看调试
-
如果var变量出现了重名,则他们会被视为同一作用域中的同一个变量
-
如果两个函数使用了相同的变量名,如果在函数内部,他们互不冲突
闭包
- 函数定义时,作用域已经确定好了,因此无论函数将来去了哪里,都能从它的作用域中找到当时那些变量
- 闭包是指函数能够访问自己的作用域中的变量
导出导入
- 需要在script标签定义一个type="module",否则不支持export(import)关键字
单个导出
-
//在表达式前面加一个export //例 export let a = 10;
一起导出
-
//在最后添加export //例 import {要导入的变量\方法\常量名字}
导出默认
-
//在最后添加export default //例 export default 默认的名字
一起导入
-
//在script标签定义一个type="module",然后使用import关键字 //例 <script type="module"> import {要导入的变量\方法\常量名字} from '导入的文件路径' </script> //要导入的变量/方法/常量名字要和一起导出的一一对应
-
导入默认
-
//在script标签里面添加import .. form //例 import 这里对应的是默认导出的变量\方法\常量等 from '导入的文件路径'
-
整体导入
-
//在script标签里面添加import * as '模块名字' form //例 import * as a from '文件路径'
方法
定义和调用
-
//定义 let 对象名 = { 属性名: 值, 方法名: 函数, get 属性名() {}, set 属性名(新值) {}, ) //调用 对象名.属性名/方法名()....
-
例
-
//定义 let stu = { name: "小明", age: 18, study: function(){ console.log(this.name+"爱学习"); } study(){ console.log(this.name+"爱学习");} //对象内时,:function可以省略 } //也可以这样写 let name = "小明"; let age = 18; let study = function(){ console.log(this.name+"爱学习"); } let stu = {name,age,study}; //调用 stu.name; stu.age; stu.study();
-
-
例2
-
//定义 let stu = { _name: null, get name(){ return this._name; //返回name }, set name(name){ this._name = name; //将原本的name替换为新name } } //调用 stu.name = "小红"; //调用set方法 stu.name; --调用get方法
-
增删
--增加方法或者属性
对象名.要新增的属性名 = 值;
//删除方法或者属性
delete 对象名.要删除的属性名;
//增加get和set
object.defineProperty(要新增的对象名,属性名,{
get(){}
set(新值){}
});
this
-
js中的this为隐式参数,但它与函数运行时上下文相关,例:一个"落单"的函数
-
function study(subject){ console.log(this.name+"在学习"+subject) //此时的this代表window的空白名字 } study("js"); //结果为 在学习 js
-
-
同样的函数,如果作为对象的方法
-
function study(subject){ console.log(this.name+"在学习"+subject) } let stu = { name: "小白", study } //这种情况下,会将当前对象作为this stu.study("js"); //结果为 小白在学习 js
-
-
动态改变this
-
function study(subject){ console.log(this.name+"在学习"+subject) } let stu = {name: "小黑"}; --返回study执行时,把call的第一个参数作为this study.call(stu,"js"); ---结果为 小黑在学习 js
-
-
例外:在箭头函数内出现的this,以外层的this理解
-
匿名函数
-
let stu = { name: "小花", friends: ["小白","小黑","小明"], play(){ this.friends.foreach(function(e){ //这个this代表stu console.log(this.name+"与"+e+"在玩耍"); //这个this代表window的空白 }); } }
-
-
箭头函数
-
let stu = { name: "小花", friends: ["小白","小黑","小明"], play(){ this.friends.foreach( e=>{ //这个this代表stu console.log(this.name+"与"+e+"在玩耍"); //这个this代表stu }) } }
-
Date
-
//当前时间(中国标准时间) var 对象名 = new Date(); //年 对象名.getFullYear(); //月 对象名.getMouth(); //日 对象名.Date(); //星期几 对象名.getDay(); //时 对象名.getHours(); //分 对象名.getMinutes(); //秒 对象名.getSeconds(); //时间戳 对象名.getTime();
Json
-
Json对象
-
{ "name": "张三", "age": 18 }
-
-
js对象
-
{ name: "张三", age: 18 }
-
不同点
- 本质不同
- json对象本质上是个字符串,它的职责是作为客户端和服务器之间传递数据的一种格式,它的属性只是样子货(在转为java/js对象之前是无法读取字符串的属性)
- js对象是切切实实的对象,可以有属性方法
- 语法细节不同
- json中只能有null,true,false,数字,字符串(只有双引号),对象,数组
- json中不能有除以上其他js对象的特性,如方法等
- json中的属性必须用双引号引起来
json字符串和js对象的转换
JSON.parse(json字符串); //返回js对象
JSON.stringify(js对象); //返回json字符串
继承
-
定义和调用
-
//创建父对象 let 父对象名 = { 属性名: 值, 方法名: 函数; } //创建子对象 let 子对象名 = Object.create(父对象名); //以create中的参数为原型创建一个子对象 //调用 子对象名.父对象名中的属性名; 子对象名.父对象名中的方法名();
-
-
例
-
//创建父对象 let father = { f1: '父属性', m1: function(){ console.log("父方法"); } } //创建子对象 let son = Object.create(father); //以create中的参数为原型创建一个子对象 --// son.f1; son.m1();
-
father是父对象,son去调用.m1或者.f1时,自身对象没有,就到父对象中寻找
-
son自己可以添加自己的属性和方法
-
son有特殊属性_proto_代表它的父对象,js术语:son的原型对象
-
不同浏览器对打印son的_proto_属性时显示不同
- edge打印从console.dir(son)显示[prototype]
- Firefox打印console.dir(son)显示
-
基于函数的继承
-
函数负责创建子对象,给子对象提供属性,方法,功能上相当于构造方法
-
函数有个特殊的属性prototype,他就是函数创建的子对象的父对象
-
//定义子对象 function cons(f2){ this.f2 = f2; //this代表子对象 this.m2 = function(){ console.log("子方法"); } } --定义父对象 cons.prototype.f1 = "父属性"; //cons.prototype就代表父对象 cons.protytype.m1 = function(){ console.log("父方法"); } --创建子对象 let son = new cons("子属性"); ----new关键字创建子对象
-
BOM对象
-
location
-
代表当前页面的URL信息
-
host:主机 href:当前地址 protocol:协议 reload:f reload();//刷新网页 //设置新的地址 location.assign(新地址);
-
-
DOM对象
获取
-
document.getElementByTagName(标签) //标签选择器 document.getElementById(Id) //Id选择器 document.getElementByClass(Class属性) //类选择器
更新
-
//修改值 选择器获取的值.innerText = "修改后的值"; //例 id.innerText = "11"; //修改字体 选择器获取的值.style.color/font = "修改后的值"; //例 id.style.color = "red";
删除
-
获取父节点,在通过父节点删除子节点
-
父节点标签名.removeChild(子节点标签名); //例 father(id起的名).removeChild("p1");
-
-
根据元素下表删除节点
-
//查看父节点下的子节点 父节点标签名.children; //删除 父节点标签名.removeChild(父节点标签名.children[下标]);
-
插入
-
如果获取的节点是空的,就可以使用innerHTML增加一个元素
-
<p id="js">js</p> <div id="list"> <p id="se">javase</p> <p id="ee">javaee</p> <p id="me">javame</p> </div> //将js插入到javame后面 //获取js标签 var js = document.getElementById('js'); //获取list标签 var list = document.getElementById('list'); //将js插入到javame后面 list.appendChild(js);
-
创建
-
<p id="js">js</p> <div id="list"> <p id="se">javase</p> <p id="ee">javaee</p> <p id="me">javame</p> </div> //在me后面新加一个p标签 //获取js标签 var js = document.getElementById('js'); //获取list标签 var list = document.getElementById('list'); //在me后面创建一个p标签 var p = list.createElement('p'); //给p标签赋值 p.innerText= "css";
表单
-
获取输入框的值
-
选择器获取的值.value
-
-
绑定事件
-
//点击 onclick
-
jQuery
-
需要导入Jquery的包
-
公式
-
$(选择器).事件 //例:单击后弹框 <!--绑定事件--> <a href="" id="test">弹框</a> <script> $('#test').click(function (){ alert('弹框'); }) </script>
-
-
选择器
- css中的选择器都能用,需要加单引号
-
事件
- 鼠标事件
- mouse开头的
- 鼠标事件