JavaScript程序设计语言完全入门
01_变量
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var n = Number.MAX_VALUE // 数字最大值
console.log(n)
var age = 18
console.log(`我今年${age}岁了`)
console.log(Myname)
var Myname
console.log(addr)
// 变量使用 var 关键字 声明
// 注意由于13行变量提升的存在, 所以第12行不会报错,只是打印了undefined
</script>
</html>
02_变量类型
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var name = 'zs'
var age = 19
var lover = ['小芳','小兰'] // typeof 无法正确检测array的类型,会统一返回 object,如果检测可以使用Array.isArray
var u // 这个变量只声明但是并没有保存变量
console.log(typeof name,name)
console.log(typeof age,age)
console.log(typeof lover,Array.isArray(lover), lover instanceof Array)
console.log(typeof u,u)
console.log(typeof a,a) // 没有赋值也没有声明,直接报错
// 用来判断一个变量是否为数组可以使用 Array.isArray(lover), 或者 lover instanceof Array来判断该变量是否为数组对象
</script>
</html>conso
03_ isNaN
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
console.log(isNaN('hello')) // is_NaN用来判断是否为非数字类型,如果是数字返回false,如果是非数字则返回true
console.log(isNaN(1))
// !! 注意对于空数组和只有一个数值成员的数组 isNaN也返回false
console.log(isNaN([])) // false
console.log(isNaN([123])) // false
console.log(isNaN(['123'])) // false
// NaN 不等于自身
console.log('is_NaN 不等于自身', NaN == NaN)
</script>
</html>
04_Boolean
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
console.log(true + 1) // bool值在和数字相加的时候 true的值为1,false的值为0
console.log(false + 1)
</script>
</html>
05_数据类型转换
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
height = 184
console.log(height.toString()) // 使用字符串的方法 toString可以强制转换该字符为字符串
console.log(String(height)) // 使用函数 String 可以强制转换该字符为字符串
console.log(height + '厘米') // 字符串相加即可转换类型
age = '18.9岁'
console.log(parseInt(age)) // parseInt 会强制去掉字符串的的非数字字符并转为int类型数字
rem = 'rem120px'
console.log(parseInt(rem)) // parseInt如果第一个字符是非数字类型则无法转换
console.log(parseFloat(age)) // parseFloat转换字符为float类型
console.log(Number('2233'),Number('2233哈哈哈')) // 使用Number转换一些纯数字字符串
console.log(Boolean(1)) // 使用Boolean转换布尔值
console.log(Boolean(0))
</script>
</html>
06_前置递增/后置递增
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var num = 10
num++
console.log(num)
++num
console.log(num )
// 自增也是一个表达式
// 1. 前置自增和后置自增如果单独使用,效果是一样的
// 2. 后置自增: 先返回原值, 后自增 +1 , 前置反之,先自增 +1 再返回新值
var num = 10
console.log(num++ + 10) // 后置自增先返回原值的10,返回到上层 + 10 所以结果是20
console.log(num) // 输出为 11 由于上方的自增表达式修改了num的值
var num = 10
console.log(++num + 10)
var e = 100
console.log(e++ + ++e) // e++是100 ++e是102(101+1) 所以返回202
</script>
</html>
07_switch和if分支判断
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let num="6";
switch(num){
case 7:
alert("数字等于7");
case "6":
alert("数字等于6");
case 5:
alert("数字等于5");
break
case 4:
alert("数字等于4");
}
// case 后面跟表达式,表达式的返回比去 "全等" 才可以达成条件
// 一个值匹配成功后,如果没有break 那么下边的case不判断,直接执行
// 当分支较少时 if...else语句的执行效率比switch语句要高
// 当分支比较多是 switch语句的执行效率比较高,且结构清晰
</script>
</body>
</html>
08_循环for
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
for(var i=0;i<100;i++){
console.log('2233')
}
let names = ['小明','小花']
for(let i of names){
console.log(i)
}
// for(初始化变量;条件表达式;操作表达式){
// 循环体
// }
// 初始化变量: 就是用 var 声明的普通变量,通常作为计数器使用
// 条件表达式: 就是循环执行的条件
// 操作表达式: 每次循环最后执行的变量, 常用于更新初始化变量
// 循环体: 循环的内部代码
</script>
</html>
09_循环while
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
i = 1
while (i <= 10) {
console.log(i)
i++ // 操作表达式
}
c = 1
do {
console.log(c)
c++
} while (c <= 10) {
}
// while 循环中也应该有操作表达式来改变初始化变量
// do while 和 while不同的是 do while是先执行代码体然后再判断是否继续执行,while则是先判断是否满足执行条件
</script>
</html>
10_array
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
arr = ['小明','小花']
arr.length = 5 // 可以直接修改 array 的 length 来改变 array 的长度
console.log(arr)
console.log(arr[3]) // 强行修改的长度是没有值的 默认是 undefined
arr = ['小明','小花']
arr[4] = '小芳' // 通过下标也可以直接增加元素
console.log(arr)
arr = []
for (var i = 0; i < 10; i++){
arr[i] = i
}
console.log(arr)
</script>
</html>
11_函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var func1 = function(num){
var c = 0
for (var i = 0; i <= num; i++) {
c+=i
}
console.log(c)
}
func1(100)
function func1(num){
}
// 声明函数的方式
// function 函数名(形参1,形参2,形参3, ...){
// 函数体
// }
// 匿名函数的声明方式
// var 函数名 = function(形参1,形参2,形参3, ...){
函数体
// }
</script>
</html>
12_函数的参数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var func = function(num1,num2){
console.log(num1 + num2)
}
func(1) // 如果没有传递正确数量的参数,则没传递的参数默认为 undefined
func(1,2)
func(1,2,3)
</script>
</html>
13_函数的返回
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var func1 = function(num1,num2){
return num1,num2
}
console.log(func1(1,2)) // 函数默认只能返回一个值,返回的结果是最后一个值
function func2(){
}
console.log(func2()) // 如果函数没有返回值,则默认返回undefined
</script>
</html>
14_函数收集参数arguments
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var func = function(){
console.log(arguments.length)
console.log(arguments)
console.log(arguments[0])
}
// arguments 是当前函数的内置对象,所有函数都内置了, arguments对象中存储了所有传递进来的实参
// arguments 是一个伪数组
func('小明','小花','小芳')
</script>
</html>
15_函数的相互调用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var func1 = function(){
console.log('func1')
func2() // 在函数中可以调用其他的函数
}
var func2 = function(){
console.log('func2')
// func1() // 小心重复调用
}
func1()
</script>
</html>
16_作用域和变量
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// 在es6之前,变量一共分为两个作用域: 全局作用域. 局部作用域(写在函数内)
var name = '小明'
function func1(){
var name = '小花'
console.log(name)
age = 15 // 没有声明直接赋值属于全局变量
}
func1()
console.log(name) // 打印了全局作用域的name
console.log(age) // 在函数内没有声明直接赋值的也归属于全局变量
</script>
</html>
17_作用域链
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var a = 100
function F1() {
var b = 200
function F2() {
var c = 300
console.log(a) // 自由变量,顺作用域链向父作用域找
console.log(b) // 自由变量,顺作用域链向父作用域找
console.log(c) // 本作用域的变量
}
F2()
}
F1()
</script>
</html>
18_预解析
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
console.log(num) // 打印 undefined 是因为预解析了(num的变量在最上面,但是还没有赋值)
var num = 10 // 到这一步才开始赋值
// 上面的两行代码预解析为下面的过程
// var num
// console.log(num)
// num = 10
fn1() // 先调用,后声明
function fn1(){
console.log('fn1')
}
fn2()
var fn2 = function(){
console.log('fn2')
}
// 匿名函数是无法进行预解析的,直接报错,上面的三行代码预解析为下面的过程
// var fn2
// fn2() fn2是不可以调用的因为fn2在这时只是一个变量
// fn2=function(){}
// 1. js引擎运行js代码分为两步: 预解析后代码执行
// (1). 预解析: js引擎会把代码中的 var 和 function 提升到当前作用域的最前面
// (2). 代码执行: 按照代码书写的顺序从上往下执行
// 2. 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
// (1). 变量预解析: 就是把所有的变量声明提升到当前的作用域最前面,但是不进行赋值操作
</script>
</html>
19_预解析案例01
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var num = 20
func() // 执行
function func(){
console.log(num)
var num = 10
}
// 上面的代码相当于执行了下面的操作
// var num
// function func(){
// console.log(num)
// var num = 10
// }
// num = 20
// func() --> function func(){
// --> var num
// --> console.log(num) // 所以这行代码打印的是undefined
// --> var num = 10
// --> }
</script>
</html>
20_预解析案例02
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
function func(){
var a = b = c = 9 // 相当于 var a = 9 ; b = 9; c = 9 由于b和c是直接赋值所以变成了全局变量
console.log(a)
console.log(b)
console.log(c)
}
func()
console.log(c) // 由于b和c变成了全局变量所以可以打印出来
console.log(b)
console.log(a)
</script>
</html>
21_对象及创建
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// var obj = {} // 创建了一个空对象
// this 的指向此时为全局对象, 谁调用方法中的this就指向谁,类似Python中的self
// 对象可以使用 . 来点出来属性,也可以类似Python中字典的方式取出相应的属性
var obj = { // 创建了一个有值的对象
name:'小明',
age:19,
say:function(){
console.log(`我叫${this.name},今年${this.age}岁了`)
}
}
var stu = new Object({ // 使用 new方法 创建一个对象
age:22
})
stu.name = '张三'
console.log(stu.name)
console.log(stu['age'])
obj.say() // 调用对象的方法
</script>
</html>
22_对象new和构造函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// 有时候需要创建的对象中有相同的属性,比如都有名字,性别,和年龄 就类似Python中的类,创建对象就是实例化这个类
// new 构造函数可以在内存中创建一个空对象,this就会指向创建的实例,执行构造函数里面的代码就给这个空对象添加了属性和方法
// 构造函数的语法格式:
// function 函数名(){
// this.name
// this.age
// this.sex
// }
function Student(name,age,sex){ // 创建一个构造函数
this.name = name
this.age = age
this.sex = sex
this.say = function(){
console.log(this) // 打印this 就打印出来了实例对象
console.log(`我叫${this.name},今年${this.age},性别${this.sex}`)
}
}
var stu1 = new Student('小明',18,'男') // 实例化
console.log(stu1.name)
stu1.say()
// 这里创建一个 对象方法的引用 到外部, 在调用的时候 say() 等同于 window.say()
var name = 'window_name'
let say = stu1.say;
say()
</script>
</html>
23_遍历对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var stu = {
name:"张三",
age:18
}
for (var k in stu) {
console.log(k,stu[k])
}
</script>
</html>
24_简单数据类型/复杂数据类型
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// 简单数据类型: 数据存放在栈中 string number boolean undefined null,内存中存放的是具体的值,类似Py中的不可变对象
// 简单数据类型 null, 是一个对象, 如果有个变量打算存储为对象暂时没有想好存啥可以用null
var t = null
console.log(typeof t)
// 复杂数据类型: 数据存放在堆中 引用类型,在栈中存的仅仅是真实数据在堆中的内存地址,而不是具体的值,类似Py中的可变对象
// 通过new关键字创建的对象(系统对象,自定义对象),如Object Array Date 等
function Student(name){
this.name = name
}
function change_name(stu){
stu.name = '2020新生--' + stu.name
}
小明 = new Student('小明')
console.log(小明.name)
change_name(小明) // 调用了函数,
console.log(小明.name)
</script>
</html>
25_对象方法keys
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
类似python中的keys 返回字典对象所有的属性名字
-->
<script type="text/javascript">
var obj = {
name: '小明',
age: 18
};
console.log(Object.keys(obj))
</script>
</body>
</html>
26_数组方法indexof
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// indexOf 方法接收一个参数,会找到该参数在array中位置的第一个元素的下标并返回
// lastIndexOf 方法会从后往前寻找对应参数的下标
// 如果没有找到匹配的参数则返回 -1
li = ['zh','ls','ww','ls']
idx = li.indexOf('ls')
console.log(idx)
idx = li.lastIndexOf('ls')
console.log(idx)
idx = li.indexOf('小明')
console.log(idx)
</script>
</html>
27_数组方法filter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
filter 返回一个新的数组,根据过滤条件
-->
<script type="text/javascript">
var arr = [2333, 1123, 214, 754]
var new_arr = arr.filter(function(value,idx,arr){
if (value > 1000) {
console.log('发现了符合条件的元素:',value)
return value
}
})
console.log(new_arr)
</script>
</body>
</html>
28_数组方法foreach
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
foreach 循环遍历数组中的每个元素传入回调函数内 类似Python中的 for i in li:pass
-->
<script type="text/javascript">
var arr = [2333, 1123, 214, 754]
arr.forEach(function(value, idx, arr) {
console.log('数组的元素:', value, ',数组的索引:', idx, ',数组本身:', arr)
})
</script>
</body>
</html>
29_数组方法push/pop
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// push 方法会在array末尾追加元素
// unshift 方法会在arry头部添加元素
// pop 会弹出array末尾的最后一个元素
let li = [1,2]
li.unshift('a')
li.push(3,4,5,6)
console.log(li)
li.pop()
console.log(li)
</script>
</html>
30_数组方法reverse/sort
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// reverse 方法会让array本身发生反转
// sort 方法会让array从小到大排序(冒泡排序),注意本身sort方法会有bug(会按照Unicode位置进行排序)
let li = [1,5,12,65,2]
li.reverse()
console.log(li)
li.sort() // 会有bug
console.log(li)
li.sort((a,b)=>b-a) // 需要传入回调函数 a-b:升序, b-a降序
console.log(li)
</script>
</html>
31_数组方法some
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
用来检测数组中是否有符合条件的元素,并返回布尔值
-->
<script type="text/javascript">
var arr = [2333, 1123, 214, 754]
var ret = arr.some(function(value,idx,arr){
return value > 2000
})
console.log(ret)
</script>
</body>
</html>
32_字符串方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// trim 返回一个消除了字符串两端空白字符的新字符串
var str = ' a b c '
console.log(str.trim())
// concat 用来拼装两个字符串
var str = 'green'
console.log(str.concat('red'))
// substr(开始下标,截取长度) 用来截取字符串
var str = 'abcdefg'
console.log(str.substr(2,3))
// replace(被替换的字符串,替换后的字符串) 替换字符串
var str = 'aabbcc'
console.log(str.replace('cc','aa'))
// split(分隔符) 从分隔符的地方切开转为array
var str = 'a-b-c'
console.log(str.split('-'))
</script>
</html>
33_异常处理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
console.log(123)
try{
console.log(a) // 这里使用一个未定义的变量
}catch(e){
//TODO handle the exception
console.log(`出错了; ${e}`)
}finally{
console.log('finally 是最后会执行的')
}
try{
throw new Error("自己抛出的错误")
}catch(e){
//TODO handle the exception
console.log(`出错了; ${e}`)
}
</script>
</html>
34_类的定义
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
1. 在创建类时,类中的 constructor 是在类初始化 new 时自动调用的方法,类似init
2. constructor 如果不写这个函数,类也会自动生成这个函数
3. this
4. 实例化时 new 不能省略,因为需要进行初始化
5. 类是没有预解析 进行变量提升的
-->
<script type="text/javascript">
// 创建一个学生类
class stu {
constructor(args) {
this.name = args
this.flag = '22333'
}
say(args) {
console.log('hello 我是', this.name, args, '岁了')
}
}
// 实例化两个对象
var xiaoming = new stu('小明')
var xiaohua = new stu('小花')
// 打印两个对象的属性
console.log(xiaohua.name)
console.log(xiaoming.name)
// 调用对象中的方法
xiaohua.say(18)
xiaoming.say(15)
// 打印继承过来的属性
console.log(xiaohua.flag)
console.dir(xiaohua)
</script>
</body>
</html>
35_类的继承
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
// 1. 继承需要使用 extends 语法
// 2. 继承会自动继承类的 init 方法不会使用自己的
// 3. super() 会调用父类中的构造方法,且子类想覆盖父类的方法 需要把super
// 4. 写在子类的构造函数内的上方
// 5. super 代表的是父类,可以使用super调用父类的方法
class Father {
constructor(x, y) {
this.x = x
this.y = y
}
money() {
console.log(this.x + this.y)
}
say(){
console.log('Father--')
}
}
class Son extends Father {
constructor(x, y) {
super(x, y) // 需要先执行父类的构造方法
this.x = x
this.y = y
}
say(){
super.say()
}
money (){
console.log(this.x - this.y)
}
}
var son = new Son(1, 2)
var son_1 = new Son(1, 3)
son.money()
son_1.money()
// son.sum(2,5)
son.say()
</script>
</body>
</html>
36_let关键字
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
let 是用来声明一个块级作用域(if for)的变量的,声明的变量只能在当前域中使用, 和var不同的是 var声明的变量是可以在外部使用的
使用 let 防止循环中的变量 污染外部变量
使用 let 声明的变量,只能先声明,再使用,没有变量提升
使用 let 声明的变量会有 暂时性死区
使用 let 声明的变量可以不需要初始值 let name;
暂时性死区: 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
-->
<script type="text/javascript">
// // 使用 var 声明的变量
// if (true) {
// var age = 19
// }
// console.log(age) // 可以打印得到
// // 使用 let 声明的变量
// if (true) {
// let name = '小明'
// if (true) {
// let gender = 'man'
// }
// console.log(gender) // 访问不到
// }
// console.log(name) // 访问不到
// // 暂时性死区
// var num = 100
// if(true){
// console.log(num)
// let num = 20
// }
// 由于下面使用了 var 定义了 i ,而且没有立即执行函数,而是,所以 下面执行的代码 打印了全局变量中的i
var arr = []
for (var i = 0; i < 2; i++) {
arr[i] = function(){
console.log(i)
}
}
arr[0]()
i = 3 // 修改了一下全局作用域中的 i 值, 可以观察得到内部的函数执行的时候调用的是外部的 i 值
arr[1]()
console.log('下面使用 let 声明:')
var arr = []
for (let i = 0; i < 2; i++) {
arr[i] = function(){
console.log(i)
}
}
arr[0]()
i = 3 // 修改 i 的值 也不会影响函数内部的调用
arr[1]()
</script>
</body>
</html>
37_const关键字
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
// 1. const 声明的变量也具有块级作用域的特点
// 2. 使用 const 声明的变量必须要有值
// 3. 使用 const 声明的变量 不能进行修改
// if (true) {
// const age = 18
// if (true) {
// const age = 20
// }
// console.log(age)
// }
// console.log(age)
// 必须要有初始值
// const name
// // 声明的变量不能更改
// const age = 18
// age = 20
// // 如果声明的是一个列表等 类似 python 中的可变对象,那对象内部是可以更改数值的
// const name = ['xiaoming','huahua']
// name[0] = 'daniu'
// console.log(name)
</script>
</body>
</html>
38_Promise基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// 1. Promise 是一个构造函数,可以通过 new 创建一个 Promise 实例
// 2. Promise new的时候可以指定需要执行的异步操作,并且 立即执行 这个异步操作
// 3. Promise 的原型对象 prototype 身上有一个 then 方法,用来预先为这个Promise指定分别叫做 resolve(成功之后的回调函数必须传) 和 reject(失败的回调函数可以不传)
// 4. Promise 表示一个异步操作,每当 new 一个实例,这个实例就表示一个具体的异步操作
// 5. 由于Promise 是一个异步操作, 所以内部拿到执行的成功和结果后,无法把结果return出去,这时候使用回调函数进行返回
// 6. 在本身的Promise实例成功的回调函数上可以返回一个新的 Promise 对象 在外面继续 .then() 详情见下案例
console.dir(Promise)
// 7. 在Promise还有一些对象方法
// 7.1 Promise.all(),并发处理多个异步任务,所有异步任务执行完毕才能得到结果
// 7.2 Promise.rece(), 并发处理多个异步任务,只要有一个任务完成就能得到结果
// // new一个Promise方法,并指定一个异步操作,每次new都会立即执行这个异步操作
// var promise = new Promise(function() {
// console.log('开始执行异步操作')
// setTimeout(function() {
// console.log('执行成功')
// }, 1000)
// })
// // 有时候我们不想new出一个 Promise 实例后立即执行这个异步操作,可以给这个Promise封装一层函数
// // 使其函数执行时才调用 Promise
// let func = function(){
// let promise = new Promise(function(){
// console.log('开始执行异步操作')
// setTimeout(function() {
// console.log('执行完毕')
// }, 1000);
// })
// return promise
// }
// func()
let func = function() {
// 将异步操作的实例 return 到外部,用于外部设置 promise实例的.then 方法中的成功和失败的回调
return new Promise(function(resolve, reject) {
// 模拟一个耗时操作
for (var i = 0; i < 599999999; i++) {
continue
}
let flag = 1
// 判断是否执行成功
if (flag == 0) { // 如果成功执行成功的回调函数
resolve(flag)
}else{
reject(flag) // 如果失败执行失败的回调函数
}
})
}
// 指定成功和失败的回调
func().then(function(flag) {
console.log('成功了', flag)
}, function(flag) {
console.log('失败了', flag)
})
</script>
</html>
39_Promise解决回调地狱
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
function func(flag) {
// 将异步操作的Promise实例 return 到外部,用于外部设置 Promise实例的.then 方法中的成功和失败的回调
return new Promise(function(resolve, reject) {
// 模拟一个耗时操作
for (var i = 0; i < 999; i++) {
continue
}
// 判断是否执行成功
if (flag != 0) { // 如果成功执行成功的回调函数
resolve(flag)
} else {
reject(flag) // 如果失败执行失败的回调函数
}
})
}
// 1. 在本身的Promise实例成功的回调函数上可以返回一个新的 Promise 对象 在外面继续 .then()
// 2. 如果 返回的是一个普通值 比如是 hello 那么会产生一个默认的 Promise 对象,保证可以一直操作
// 3. then 方法,用来预先为这个Promise指定分别叫做 resolve(成功之后的回调函数必须传) 和 reject(失败的回调函数可以不传)
// 4. 如果前面的任务失败了但是若不想影响到后面任务的正常执行,我们可以单独为每个Promise指定失败的回调
// 5. catch 如果前面的任务有出错我们不想后面的任务继续执行,可以指定 catch 捕获异常,并终止后续回调的执行,异常捕捉采用就近原则
// 6. 通过 finally 可以指定回调链中不论成功或者失败 都会执行
func(0).then(function(flag) { // 指定任务1 的回调
console.log('成功了', flag)
// 成功之后返回任务1的回调实例
return func(1)
}, function(flag) {
// 失败了之后也返回任务2的实例
console.log('失败了', flag)
return func(2)
}).then(function(flag) { // 指定任务2 的成功回调
console.log('成功了', flag)
// 成功之后返回任务3的回调实例
return func(3)
}).then(function(flag) { // 指定任务3 的成功回调
console.log('成功了', flag)
return 'hello' // 返回一个普通的值让下面接收,会产生一个默认的Promise对象
}).then(function(flag) {
console.log(flag)
}).then(function(flag) {
console.log(flag)
})
// func(1).then(function(flag) { // 指定任务1 的回调
// console.log('成功了', flag)
// // 成功之后返回任务2的回调实例(这里手动让他出错 )
// return func(0)
// }).then(function(flag) { // 指定任务2 的成功回调
// console.log('成功了', flag)
// // 成功之后返回任务3的回调实例
// return func(3)
// }).then(function(flag) { // 指定任务3 的成功回调
// console.log('成功了', flag)
// }).catch(function(err) { // 捕捉错误
// console.log('捕捉到一个异常:',err)
// }).finally(function(){
// console.log('不论成功与失败或者报错都会执行')
// })
console.log('ok')
</script>
</html>
40_async/await关键字
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
// 1. async声明的函数会立即返回一个Promise对象,(async函数的返回值其实也是Promise实例对象),可以.then .catch
// 2. await关键字只能用于 async 函数中只有await后面的表达式执行完毕之后,代码才会继续往下执行
// 3. await 后面的参数需要跟一个 Promise 实例对象来表示需要异步执行的操作,如果传其他的东西会自动转成Promise对象
// 5. 注意! let ret = await fn(1); console.log(ret)等价于 fn('1').then((args)=>{console.log(args)}) 的语法糖
// 6. 只要 await 预计后面的 Promise 状态变成 reject 那么整个async函数会终止执行
// 7. async函数中如果有错误会影响到后面代码的执行,可以通过 try catch 进行局部捕捉异常
// 8. 也可以通过 Promise 本身提供的 catch 进行异常捕捉,异常捕捉会就近原则
// 创建一个 Promise 相关的函数
function fn(flag) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (flag) {
resolve(flag)
} else {
reject('失败:' + flag)
}
}, 1000)
})
}
async function func() {
// 手动引发一个异常,并局部进行捕捉
await Promise.reject('出现问题了').catch(err=>{})
let ret_1 = await fn(1)
console.log(ret_1)
let ret_2 = await fn(2)
console.log(ret_2)
let ret_3 = await fn(3)
console.log(ret_3)
}
// 由此可见 async 函数执行后会立即返回一个 Promise对象
let fn_obj = func()
console.log(fn_obj)
fn_obj.then(res => {
console.log(res)
}).catch(err => {
console.log('捕捉到异常:',err)
})
</script>
</html>
41_axios基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script src="axios.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// axios的post请求默认传递的是json 格式的数据
// axios的API 第二个参数可以接收一个对象用来传递多个参数
// 表单请求需要实例化一个URLSearchParams对象用于创建数据
// 后台返回的json格式的数据 axios 会封装成一个对象方便调用
// // 查询字符串传参
// axios.get('http://192.168.72.136:5000/hello?user_id=849317537')
// .then(function(ret){
// console.log(ret)
// console.log(ret.data)
// })
// // 请求路径传参
// axios.get('http://192.168.72.136:5000/say/849317537')
// .then(function(ret){
// console.log(ret)
// console.log(ret.data)
// })
// // 多个查询字符串传参
// axios.get('http://192.168.72.136:5000/hello',{
// params:{
// user_id:'849317537',
// age:'12'
// }
// }).then(function(ret){
// console.log(ret.data)
// })
// // POST请求(默认json格式)
// axios.post('http://192.168.72.136:5000/post_test',{
// user_id:'13673429931',
// gender:'man'
// }).then(function(ret){
// console.log(ret.data.user_id,ret.data.gender)
// })
// // form表单请求
// let params = new URLSearchParams()
// params.append('user_id','13673429931')
// params.append('pwd','1234')
// axios.post('http://192.168.72.136:5000/form_test',params).then(function(ret){
// console.log(ret.data.user_id,ret.data.pwd)
// })
// put请求
axios.put('http://192.168.72.136:5000/post_test', {
user_id: '13673429931',
gender: 'man'
}).then(ret=> {
console.log(ret.data.user_id, ret.data.gender)
})
console.log(123)
</script>
</html>
42_axios配置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script src="axios.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
axios.defaults.timeout = 3000 // 超时时间
axios.defaults.baseURL = 'http://192.168.72.136:5000' // 设置基础请求路径
axios.defaults.headers = {'token':'23333'} // 设置请求头
// // 因为设置了 baseURL 可以省略前面的路径
// axios.get('/hello?user_id=849317537')
// .then(function(ret){
// console.log(ret)
// console.log(ret.data)
// })
axios.get('/token')
.then(function(ret){
console.log(ret)
console.log(ret.data.Token)
})
</script>
</html>
43_axios拦截器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script src="axios.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
axios.defaults.baseURL = 'http://192.168.72.136:5000'
// 1. 请求拦截器会在请求发送到服务器之前进行一些相关的配置
// 2. 在拦截器中的函数中,接收两个形参用于处理配置和失败的调用函数
// 3. 配置axios的选项的函数接收一个形参用来表示axios的设置选项,这个形参必须要return出去
axios.interceptors.request.use(function(cfg) {
cfg.headers['Token'] = '23333' // 在拦截器中设置请求头
console.log(cfg) // 打印一下拦截器的配置
return cfg
}, function(err) {
console.log(err)
})Authorization
// 1. 响应拦截器,会在服务器返回时,对响应做一些处理
// 2. 拦截器接收两个函数用来处理配置和错误的处理
// 3. 其中配置的函数会接收一个形参用于接收 服务器返回的 response,进行加工后可以对外部返回数据
axios.interceptors.response.use(function(res) {
console.log(res)
let data = res.data
return data
}, function(err) {
console.log(err)
})
axios.get('/token')
.then(function(ret) {
console.log(ret.Token)
// console.log(ret.data.Token)
})
</script>
</html>