跳转至

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>