只因小黑子的JavaScript入土过程第五章

小黑子的JavaScript入土过程第五章

JavaScript系列教程第五章

5.1 初识正则表达式

正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
搜索模式可用于文本搜索和文本替换。

什么是正则表达式?

  1. 正则表达式是由一个字符序列形成的搜索模式。
  2. 当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容。
  3. 正则表达式可以是一个简单的字符,或一个更复杂的模式。
  4. 正则表达式可用于所有文本搜索和文本替换的操作。

为什么要用正则表达式?

用正则表达式,是为了让我们能够更方便、更灵活的搜索和替换文本。

如果说,之前我们用字符串搜索文本是精准查询的话,用正则表达式查询就是模糊查询,它的搜索范围可以更广。

案例:应用校验输入框的内容

  <form action="">
    <input type="text" required id="mytext">
    <input type="emaill">
    <input type="submit" value="submit">
  </form>
  <script>
  //正值表达式一般写法
    //1 字面量写法 :/ /
    var reg = /abc/ //目的:将来检测字符串时是不是包含abc
    console.log(reg)

    //2.内置构造函数
    var reg2 = new RegExp("abc")
    console.log(reg2)

    mytext.onblur = function() { //onblur失去聚焦时触发事件
      console.log(mytext.value)
      console.log(reg.test(mytext.value))//test()测试方法,测试mytextt.valuez中是否包含abc
    }   
  </script>

在这里插入图片描述

5.2 元字符-基本元字符

5.2.1 \d 包含数字符合

  • \d 一位数字(0-9)写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\d\d/
    console.log(reg.test("abc"))
    console.log(reg.test("123")) //字符串中包含也符合
    console.log(reg.test("1"))
  </script>

在这里插入图片描述

5.2.2 \D 包含至少一位非数字

  • \D 一位非数字写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\D\D/
    console.log(reg.test("abc"))
    console.log(reg.test("123"))
    console.log(reg.test("1"))
  </script>

在这里插入图片描述
案例:
有k才可以

  <script>
    var reg = /\Dk\D/
    console.log(reg.test("abc"))
    console.log(reg.test("123"))
    console.log(reg.test("1"))
    console.log(reg.test("aka"))
  </script>

在这里插入图片描述

5.2.3 \s 有一位空白(空格 缩进 换行)

  • \s 一位空白(空格 缩进 换行)写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\s/
    console.log(reg.test("a    bc"))
    console.log(reg.test("12\n3"))
    console.log(reg.test("1"))
    console.log(reg.test("a ka"))
  </script>
</body>

在这里插入图片描述

5.2.4 \S 有一位非空白内容

  • \S 至少有一位非空白内容,写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\S/
    console.log(reg.test("a    bc"))
    console.log(reg.test("12\n3"))
    console.log(reg.test("    "))
    console.log(reg.test("\n\n\n"))
  </script>

在这里插入图片描述

5.2.5 \w 有一位字母or数字or下划线

  • \w 至少有一位字母or数字or下划线,写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\w/
    console.log(reg.test("&"))
    console.log(reg.test("12\n3"))
    console.log(reg.test("wdnmd"))
    console.log(reg.test("c_n_m"))
  </script>

在这里插入图片描述

5.2.6 \W 有一位非字母or数字or下划线

  • \W 至少有一位非字母or数字or下划线,写一个就是包含一位就符合,写两个就是包含两位就符合,依次类推
  <script>
    var reg = /\W/
    console.log(reg.test("&"))
    console.log(reg.test("12\n3"))
    console.log(reg.test("wdnmd"))
    console.log(reg.test("c_n_m"))
  </script>

在这里插入图片描述

5.2.7 . 任意内容(换行不算)

  <script>
    var reg = /./
    console.log(reg.test("&%^*#@4¥"))
    console.log(reg.test("12\n3"))
    console.log(reg.test("\n\n\n\n"))
    console.log(reg.test("c_n_m"))
  </script>

在这里插入图片描述

5.2.8 .\ 转义字符

  <script>
    var reg = /\d\.\d/  //要求写1.2 2.3类型的
    console.log(reg.test("1.2"))
    console.log(reg.test("1a3"))
    console.log(reg.test("\n\n\n\n"))
    console.log(reg.test("c_n_m"))
  </script>

在这里插入图片描述

5.3 元字符-边界符

5.3.1 ^ 设定开头

^ 表示开头有才行

  <script>
    var reg = /^\d/ //表示开头有数字才可以
    console.log(reg.test("1.2"))
    console.log(reg.test("1a3"))
    console.log(reg.test("\n\n\n\n"))
    console.log(reg.test("c_n_m"))
  </script>

5.3.2 $ 设定结尾

$表示结尾有才行

  <script>
    var reg = /\d$/
    console.log(reg.test("1.2"))
    console.log(reg.test("1a3"))
    console.log(reg.test("12\n"))
    console.log(reg.test("c_n_m"))
  </script>

在这里插入图片描述
案例:

  <script>
    var reg = /^a\dc$/ //表示开头要有a,中间是一个任意的数字,结尾是c
    console.log(reg.test("1.2"))
    console.log(reg.test("1a3"))
    console.log(reg.test("a6666666c"))
    console.log(reg.test("a6c"))
  </script>

在这里插入图片描述

5.4 元字符-限定符

5.4.1 * 实现0~多次

限定符* 表示出现0次或多次都可以

  <script>
    var reg = /\d*/
    console.log(reg.test("abc"))
    console.log(reg.test("ab1"))
    console.log(reg.test("a6666666c"))
  </script>

在这里插入图片描述

5.4.2 + 实现1~多次

  <script>
    var reg = /\d+/
    console.log(reg.test("abc"))
    console.log(reg.test("ab1"))
    console.log(reg.test("a6666666c"))
  </script>

在这里插入图片描述

5.4.3 ? 匹配任何包含0个或1个

等效于 {0,1}

  <script>
    var reg = /\d?/
    console.log(reg.test("abc"))
    console.log(reg.test("ab1"))

  </script>

在这里插入图片描述

5.4.4 {n} 指定次数

{n}表示出现n次;
{n,}表示出现n次或多次
{n,m} 表示出现n到m的次数

  <script>
    var reg = /\d{3}/
    console.log(reg.test("abc"))
    console.log(reg.test("ab1"))
    console.log(reg.test("a123"))
  </script>

在这里插入图片描述

5.5 元字符-特殊字符

  1. ( ) 表示整体
  2. | 表示或
  3. 代表1个字符

[a-zA-Z0-9] 相当于\w

[0-9] 相当于 \d

案例:
1.

  <script>
    var reg = /[a-z]{3,5}/ //表示a-z之间出现至少3到5次
    console.log(reg.test("abc"))
    console.log(reg.test("def"))
    console.log(reg.test("bbbbbbbbb1.234567"))
  </script>

在这里插入图片描述
2.

  <script>
    var reg = /[^abc]/ //表示不在abc范围之内的
    console.log(reg.test("abc"))
    console.log(reg.test("def"))
    console.log(reg.test("ab"))
  </script>

在这里插入图片描述

5.6 正则表达式-exec() 捕获

  <script>
    var datester = "time is 2029-01-01 12:20:20"
    var reg = /\d{4}-\d{1,2}-\d{1,2}/
    var newdatestr = reg.exec(datester)//以reg的数字出现结构,获取datester的
    console.log(newdatestr[0])
    console.log(newdatestr[0].split("-")) //将其转换为数组
    console.log(newdatestr[0].split("-").join("/")) //转换字符串
  </script>

在这里插入图片描述

5.6.1 标识符

标识符Value
i执行对大小写不敏感的匹配。
g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m执行多行匹配。

g案例:

  <script>
    var datester = "time is 2029-01-01 12:20:2 to 2030-11-01 12:20:2  "
    var reg = /\d{4}-\d{1,2}-\d{1,2}/g
    var newdatestr1 = reg.exec(datester)
    console.log(newdatestr1[0])
    
    var newdatestr2 = reg.exec(datester)
    console.log(newdatestr2[0])
    
    var newdatestr3 = reg.exec(datester)
    console.log(newdatestr3[0])
  </script>

在这里插入图片描述
i案例:

  <script>
    var reg = /[a-z]/i
    console.log(reg.test("AA"))
    console.log(reg.exec("AA"))

  </script>

在这里插入图片描述

5.7 正则表达式的两大特性

  1. 懒惰,解决方案:使用全局标识符g
    “惰性”表示匹配最短的字符串
  2. 贪婪 ,解决方案:使用特殊符号?

贪婪表示将匹配尽可能大的组,惰性表示将匹配最小的组

贪婪限定符	惰性限定符
*	           *?	
+	           +?	
?	           ??	
{ n}	       {n}?
{ n,}          {n,}?
{ n,m}	       {n,m}?
     var reg=/\d{1,4}/   //我要的是至少一次到至多4次
     var str='aa1234bb'
     console.log(reg.exec(str))

在上面这几串代码中,有时候仅仅只需要一次就足以,但是它会将所有符合的都捕获出来,在这里的话也就是四次。

对贪婪这个特性我们也是有解决方案的,那就是在正则表达式的后面,给他加上一个问号。如下

     var reg=/\d{1,4}?/   

在加上问号之后他就会转为一种非贪婪模式,这样子就会在我们碰到第一个符合的字符就会停下来,不会再往下继续操作了。

5.8 正则与字符串方法

5.8.1 replace()替换
  <script>
    var str = "adearfa"
    var newstr = str.replace("a","*")
    console.log(newstr)

    var newstr = str.replace(/a/g,"*")
    console.log(newstr)

  </script>

在这里插入图片描述

5.8.2 search()查找索引

  <script>
    var str = "adearfa"
    var newstr = str.replace("a","*")
    console.log(str.search("a"))
    console.log(str.search(/a/g))

  </script>

但是,加了g的标识符,最后的a也没有查到索引,只能找到第一个
在这里插入图片描述

5.8.3 mach() 捕获内容

mach()匹配想要的内容,必esec()好用

  <script>
    var datester = "time is 2029-01-01 12:20:2 to 2030-11-01 12:20:2  "
    console.log(datester.match(/\d{4}-\d{1,2}-\d{1,2}/))
    console.log(datester.match(/\d{4}-\d{1,2}-\d{1,2}/g))
  </script>

在这里插入图片描述

5.9 密码强度验证案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
     * {
      margin: 0;
      padding: 0;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    form {
      width: 500px;
      padding: 20px;
      border: 3px solid #333;
    }

    form>label {
      width: 100%;
      height: 70px;
    }

    form > label > input {
      width: 100%;
      box-sizing: border-box;
      font-size: 20px;
      height: 50px;
    }

    form>p {
      width: 100%;
      margin-top: 10px;
      display: flex;
      justify-content: space-between;
    }

    form>p>span {
      width: 30%;
      background-color: #CCC;
      color: #fff;
      height: 30px;
      font-size: 20px;
      line-height: 30px;
      text-align: center;
    }

    form>p>span:nth-child(1).active {
      background-color: red;
    }

    form>p>span:nth-child(2).active {
      background-color: orange;
    }

    form>p>span:nth-child(3).active {
      background-color: green;
    }
</style>
<body>
    <form>
        <label>
            <input type="text">
        </label>
        <p>
            <span></span>
            <span></span>
            <span></span>
        </p>
    </form>
    <script>
        var oinput = document.querySelector("input")
        var ospan = document.querySelectorAll("span")
        
        var reg1 = /\d/
        var reg2 = /[a-z]/i
        var reg3 =/[!@#$%^&*()]/
        oinput.oninput = function(){
            // console.log(this.value)
            var level = 0

            if(reg1.test(this.value)) level++
            if(reg2.test(this.value)) level++
            if(reg3.test(this.value)) level++
            
            for(var i=0;i<ospan.length;i++){
                ospan[i].classList.remove("active")
                if(i<level){
                    ospan[i].classList.add("active")
                }
            }
        }
    </script>
</body>
</html>

在这里插入图片描述

5.9 this 指向

tihs: 谁调用我,this就指向谁

  • 在方法中,this 表示该方法所属的对象。
  • 如果单独使用,this 表示全局对象。
  • 在函数中,this 表示全局对象。
  • 在函数中,在严格模式下,this 是未定义的(undefined)。
  • 在事件中,this 表示接收事件的元素。
  • 类似 call() 和 apply() 方法可以将 this 引用到任何对象。

单独使用 this
单独使用 this,则它指向全局(Global)对象。
在浏览器中,window 就是该全局对象为 [object Window];

方法中的 this
在对象方法中, this 指向调用它所在方法的对象。

    <script>
        var obj = {
            name:"steve",
            test:function(){
                console.log("11111",this)
            }
        }
        obj.test()
    </script>

在这里插入图片描述

事件中的 this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素:

    <div id="box">
        click
        <span>11111</span>
    </div>
    <script>
        box.addEventListener(
            "click",function(evt){
                console.log(evt.target)
                console.log("11111",this)
            }
        )
    </script>

在这里插入图片描述

5.10 改变this指向

    <script>
        var obj1 = {
            name:"obj1",
            getName:function(){
                console.log("getName1",this.name)
            }
        }
        var obj2 = {
            name:"obj2",
            getName:function(){
                console.log("getName2",this.name)
            }
        }

        //打算让obj1的this.name指向obj2的getName
        obj1.getName()
        obj2.getName()
    </script>

在这里插入图片描述

5.10.1 call 和 apply 执行函数,并改变this执行为函数的第一个参数

        obj1.getName.call(obj2)
        obj1.getName.apply(obj2)

在这里插入图片描述
call于apply的区别:
call:支持多给参数
apply:两个参数,第二个参数是一个数组

        var obj1 = {
            name:"obj1",
            getName:function(a,b,c){
                console.log("getName1",this.name)
                console.log("参数",a,b,c)
            }
        }
        var obj2 = {
            name:"obj2",
            getName:function(){
                console.log("getName2",this.name)
            }
        }

        //打算让obj1的this.name指向obj2的getName
        obj1.getName.call(obj2,1,2,3)
        obj1.getName.apply(obj2,[1,2,3])

在这里插入图片描述

5.10.2 bind 改变this指向为函数的第一个参数,不会自动执行函数

bind也支持多个参数,要手动执行

        var obj1 = {
            name:"obj1",
            getName:function(a,b,c){
                console.log("getName1",this.name)
                console.log("参数",a,b,c)
            }
        }
        var obj2 = {
            name:"obj2",
            getName:function(){
                console.log("getName2",this.name)
            }
        }

        var fun1 = obj1.getName.bind(obj2,1,2,3)
        console.log(fun1)
        fun1()//手动执行

在这里插入图片描述

5.11 ES6定义变量

  • 我们所说的ES5和ES6其实就是在js语法的发展过程中的一一个版本而已
  • ECMAScript 就是js的语法
  • 。以前的版本没有某些功能
  • 。在ES5这个版本的时候增加了一些功能
  • 。在ES6这个版本的时候增加了一些功能
  • 因为浏览器是浏览器厂商生产的
  • 。ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能.
  • 。这个过程是需要时间的
  • 。所以到现在,基本上大部分浏览器都可以比较完善的支持了
  • 。只不过有些浏览器还是不能全部支持
  • 。这就出现了兼容性问题
  • 。所以我们写代码的时候就要考虑哪些方法是ES5或者ES6的,看看是不是浏览器都支持

let与var的区别:

  1. 必须先定义再使用,不能像var一样可以在定义前使用
  2. 变量重名会报错,不能像var一样重名会覆盖
  3. 块级作用域{ },在局部定义只能作为局部变量使用。

let与const的区别:

  1. let声明变量,const声明常量
  2. let可以定义一个名而不赋予值,const则不行

特殊案例:

    <script>
       const obj = {
        name:"steve"
       }

       obj.name = "xiaoming"
       console.log(obj)

       obj = {
        name:"xiaoming"
       }
       console.log(obj)

    </script>

前者能变是因为对象是一个复杂类型,改变的是栈里面的值,相当于把内容换了。
后者是改了地址,所以报错
在这里插入图片描述

5.12 ES6的箭头函数

    <script>
        var test1 = function () {
            console.log(11111)
        }
        //箭头函数相当于上方使用
        var test2 = () => {
            console, log(22222)
        }
        test1()
        test2()
    </script>

1.( )只有一个形参的时候可以省略

    <script>
        var test = a=>{
            console.log(111,a)
        }
        test("steve")
    </script>

在这里插入图片描述

2.{ }可以省略只有一句代码,只有返回值的时候省略return

    <script>
        var test = a=>100*a;
        console.log(test(10))
    </script>

在这里插入图片描述
综合运用:

    <script>
        var list = ["aaa","bbb","ccc"]
        var newlist = list.map(item=>`<li>${item}</li>`)
        //将list的数组元素以li表现出来
        console.log(newlist.join(""))
    </script>

在这里插入图片描述
特殊案例:
当{}省略时,使用对象结构,会把对象的花括号当成函数的换括号

    <script>
        var test = ()=>{
            name:"steve"
        }
        console.log(test())
    </script>

在这里插入图片描述
可以修改成加个()

   <script>
        var test = ()=>({
            name:"steve"
        })
        console.log(test())
    </script>

3.箭头函数没有arguments用法

arguments是保存着所有实参的伪数组,不用写形参也可以。

    <script>
        var test = function (a, b, c) {
            console.log(a, b, c)
            console.log(arguments)
            console.log(arguments[0], arguments[1], arguments[2])
        }
        test(1, 2, 3)
        test(1,2,3)
    </script>

在这里插入图片描述

4.箭头函数的this是父级作用域的

一般函数中直接用this.value是访问window的,而要打印需要临时变量储存

    <script>
        mytext.oninput = function(){
            var that = this //用临时变量储存
            setTimeout(
                function(){
                    console.log(that.value)
                },1000
            )
        }
    </script>

箭头函数的this指向外面作用域,就不用像一般函数一样储存this,功能与其一样

    <input type="text" id="mytext">

    <script>
        mytext.oninput = function(){
            //var that = this
            setTimeout(
                ()=>{
                    console.log(this.value)
                },1000
            )
        }
    </script>

在这里插入图片描述

5.函数的默认参数

当忘记写传参回答时,会导致未定义,可以导致奔溃
所以在设置参数时,可以赋予初始值,未传参就使用默认的

    <script>
        function test(a=1,b=2){
            return a+b
        }
        console.log()
        
        var test=(a=1,b=2)=>
           { return a+b}
        
        console.log()
    </script>

在这里插入图片描述

5.13 ES6的结构赋值

5.13.1 快速地从对象和数组中获取里面的成员

1.es6的获取只能按顺序获取,想要直接取中间或最后一个不行

    <script>
        var arr = ["steve","van","wot"]
        let[x,y,z] = arr
        console.log(x,y,z)
    </script>

在这里插入图片描述
2.变量交换数值

    <script>
        var a=20
        var b=10
        var[b,a]=[a,b]
        console.log(a,b)
    </script>

在这里插入图片描述
3.多维度数组获取

    <script>
        var arr2 = [1,2,[3,4,[5]]]//多维度数组
        var [q,w,[e,r,[t]]] = arr2//写出相同结构参数
        console.log(t)//输入想求的数
    </script>

在这里插入图片描述
4.复杂对象获取

    <script>
        var obj = {
            name:"steve",
            age:"100",
            location:{
                province:"magua",
                city:"youbin"
            },
            hobby:[111,222,333]
        }
        let {
            name,
            age,
            location:{
                province,
                city
            },
            hobby:[m,n,k]
        } = obj
        
        console.log(name,age,province,city,m,n,k)
    </script>

在这里插入图片描述

5.14 ES6的对象简写

1.省去了对象元素冒号写法

     <input type="text" id="myusername">
     <input type="password" id="mypassword">
     <button id="mybtn">login</button>
    <script>
        mybtn.onclick = function() {
            let username = myusername.value
            let password = mypassword.value
            console.log(username,password)
            // var obj = {
            //     username:username,
            //     password:password
            // }
            var obj = {
                username,//省去了username:username写法
                password
            }
            console.log("发给后端",obj)
        }
        
    </script>

在这里插入图片描述
2.省略函数

    <script>
        var obj = {
            a: 1,
            // getName: function () {
            //     console.log(this.a)
            // }
            getName() {
                console.log(this.a)
            }
        }
        obj.getName()
    </script>

在这里插入图片描述

5.15 ES6展开运算符

5.15.1 … 展开数组

合并

    <script>
        var a = [1,2,3]
        var b = [4,5,6]
        var c = [...a,...b]
        console.log(c)
        
    </script>

在这里插入图片描述

5.15.2 …复制

    <script>
        var a = [1,2,3]
        var b = [...a]
        b[0] = "steve"
        console.log(a,b)
        
    </script>

在这里插入图片描述

5.15.3 …参数-实参-形参

1.如此写法,…arr只能写在最后

    <script>
        var test = (a,b,...arr)=>{
            console.log(arr)
        }
        test(1,2,3,4,5)
        var test = (...arr)=>{
            console.log(arr)
        }
        test(1,2,3,4,5)
    </script>
</body>

2.传入实参

    <script>
        var arr = [1,2,3]
        var test = function(a,b,c){
            console.log(a,b,c)
        }
        test(...arr)
    </script>

在这里插入图片描述
3.判断应用

    <script>
        var arr = [12,21,4124,12541,51,25121,231]
        var res = Math.max(...arr)
        console.log(res)
    </script>

在这里插入图片描述

5.15.4 …伪数组转换

    <script>
        function test(){
            var arr = [...arguments]
            console.log(arr)
        }
        test(1,2,3,4,5)
    </script>

在这里插入图片描述
2.

    <script>
        var oli = document.querySelectorAll("li")
        var oliarr = [...oli]
        console.log(oliarr)
        console.log(oliarr.filter)
    </script>

在这里插入图片描述

5.15.5 …对象

    <script>
        var obj1 = {
            name:"steve",
            age:"100"
        }
        var obj2 = {
            name:"wot",
            location:"van"
           
        }
        var obj = {
            ...obj1,
            ...obj2
        }
        console.log(obj)
    </script>

在这里插入图片描述
修改案例应用:

   <h1>修改</h1>
    <input type="text" id="myusername">
    <input type="number" id="myage">
    <button id="btn">修改</button>
    <div id="box"></div>

    <script>
        var obj = {
            name:"steve",
            age:100,
            location:"van",
            id:"13516515416024"
        }
        function render({name,age,location}){
            // console.log(obj)
            box.innerHTML = `name:${name},age:${age}
            ,location:${location}`
        }
        render(obj)
        btn.onclick = function(){
            var name = myusername.value
            var age = myage.value
            var newobj = {
                ...obj,
                name,
                age
            }
            console.log(newobj)
            //传给后端
            //重新渲染页面
            render(newobj)
        }
    </script>

在这里插入图片描述

5.16 ES6模块化语法

什么是模块化?
将一个js文件按照功能作用分解为多个js文件,按照顺序排列多个js文件,不可胡乱排版

例如:
A.js文件和B.js文件, C.js文件要用到A和B的比分说冒泡排序和选择排序,如果把C提到A与B的前面,那么按照程序从上往下读,就会报错

为什么要使用模块化
使用模块化可以对不同的功能点进行统一管理,降低耦合性,减少同名的影响。每一个模块都有单独的空间。

ES6模块化语法也有兼容性问题
// webpack
模块化
1.私密不漏

在html中,若要导入js文件的方法
js需导出,利用export{方法A1() }
html中引入,例子
<script type ="js的所属文件夹">
import{A1} from '该js文件的地址'
该方法
</script>

2.重名不怕
当多个js文件中有重名时,例子:
import{A1,test} from ‘该js文件的地址’
import{B1,test} from ‘该js文件的地址’

<script type ="js的所属文件夹">
import{A1,test as A_test} from '该js文件的地址'
import{B1,test as B_test} from '该js文件的地址'
使用
A_test()
B_test()
</script>

3.依赖不乱

默认导出
C.js文件中导出expor default C
html:
导入一个c方法时,可以瞎写,相当于自定义了一个变量引用,结果是一样的

<script type ="js的所属文件夹">
import CCCCCC from '该js文件的地址'
该方法
</script>

5.17 初识面向对象

  • 首先,我们要明确,面向对象不是语法,是-一个思想, 是-种编程模式
  • 面向:面(脸),向(朝着)
  • 面向过程:脸朝着过程=》关注着过程的编程模式
  • 面向对象:脸朝着对象=》关注着对象的编程模式
  • 实现一个效果
  • 。在面向过程的时候,我们要关注每一 个元素,每一 个元素之间的关系,顺序,。。。
  • 。在面向过程的时候,我们要关注的就是找到一个对象来帮我做这个事情,我等待结果
  • ●我们以前的编程思想是,每一个功能,都按照需求一 步- 步的逐步完成

创建对象的方式

  • 因为面向对象就是一个找到对象的过程
  • 所以我们先要了解如何创建一 个对象

调用系统内置的构造函数创建对象

  • js给我们内置了一个Object构造函数
  • 这个构造函数就是用来创造对象的

5.18 创建对象的方式

我们平时一般创建对象都是为了解决一个问题像是做一道菜,如下:

    <script>
        //字面量
        var obj1 = {
            name:"steve",
            material:["1111","2222","3333"],
            setCook(){

            }
        }
        //内置构造函数 new Object()
        var obj2 = new Object()
        obj1.name = "steve"
    </script>

但,要是有一大堆菜要做,我们要复制粘贴相同的代码,然后去修改,就非常麻烦。

5.18.1 工厂函数

使用工厂函数,输入想要改变的值

    <script>
        //工厂函数
        function createObj(name){
            var obj = {}
            obj.name = name,
            obj.material = []
            return obj
        }
        var obj1 = createObj("steve")
        console.log(obj1)
        var obj2 = createObj("van")
        console.log(obj2)

    </script>

在这里插入图片描述

5.18.2 自定义函数

    <script>
        //自定义函数
        //不同于本来有的函数new Object() new String() new Array()
        function createObj(name){
            this.name = name
            this.marterial = []
            this.cook = function(){
            //this指向的就是函数自动创建的对象
            }
            //自动返回
        }
        var obj1 = new createObj("steve")
        var obj2 = new createObj("van")
        console.log(obj1,obj2)
    </script>

在这里插入图片描述

5.19 构造函数注意问题

  1. 首字母大写,虽然不写没有问题但是不规范

案例:

    <script>
        function CreatObj(name){
            this.name = name
        }
        var obj1 = new CreatObj("steve")
        console.log(obj1)
    </script>

在这里插入图片描述

  1. 构造函数不写return

  2. 构造函数能当普通函数用

    <script>
        function CreatObj(name) {
            console.log(this)
            this.name = name
            
        }
        var obj1 = new CreatObj("steve")
        console.log(obj1,window.name)
    </script>

在这里插入图片描述

5.19.1 this的指向问题

new的过程===实例化的过程
当实例对象已经生成时,this就是指向实例完的对象
而this有了name属性,创建一个对象obj1,就相当于把实例化对象的地址给了obj1,就是将this.name=输入的名赋值给了obj1而已
1.

    <script>
        function CreatObj(name) {
            console.log(this)
            this.name = name
            
        }
        var obj1 = new CreatObj("steve")//new的过程===实例化的过程
        console.log(obj1,window.name)
    </script>

obj1是能够调用cook这个方法的,调用时this实现谁调用我,我就指向谁的原则,所以在这里this指向了obj1

    <script>
        function CreatObj(name) {
            console.log(this)
            this.name = name
            this.cook = function(){
                console.log(this.name)
            }
        }
        var obj1 = new CreatObj("steve")
        console.log(obj1,window.name)
        obj1.cook()
    </script>

5.20 面向对象的原型

原型的好处:共享内存

    <script>
        var data1 = {
            title: "体育",
            list: ["体育-1", "体育-2", "体育-3"]
        }
        var data2 = {
            title: "综艺",
            list: ["综艺-1", "综艺-2", "综艺-3"]
        }
        function CreateList(select, data) {
            this.ele = document.querySelector(select)
            this.title = data.title,
                this.list = data.list

            //this.render=
        }
        //原型
        CreateList.prototype.render = function () {
            //渲染页面
            var h1 = this.ele.querySelector("h1")
            var ul = this.ele.querySelector("ul")
            //console.log(h1,ul)
            h1.innerHTML = this.title
            ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("")
        }
        var obj1 = new CreateList(".box1", data1)
        //var obj2 = new CreateList(data1.title,data1.list)

        //console.log(obj1)
        obj1.render()
        //console.log(obj2)
        var obj2 = new CreateList(".box2", data2)
        obj2.render()
    </script>

在这里插入图片描述

原型

new构造函数的时候,复杂数据类型是重新开辟新的内存空间,会浪费内存和降低运行速度。
请看下面示例:

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
  this.sing = function () {
    console.log('我会唱歌');
  }
}

let ldh = new Star('刘德华', 18)
let zxy = new Star('张学友', 2)
console.log(ldh.sing === zxy.sing); // false

通过 === 符号,我们可以知道 这两个方法的内存地址是不一样的!
那么 在ES6出来之前,是怎么实现继承的同时又解决掉这个问题的呢?

答案是:原型!
构造函数通过原型分配的函数是所有对象所共享的。

Javascript规定,每一个构造函数都有一个 prototype属性,指向另一个对象。
注意这个 prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

我们可以把那些不变的方法,直接定义在 prototype对象上,这样所有对象的实例就可以共享这些方法

接下来改进一下我们的 Star构造函数:

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
  // this.sing = function () {
  //   console.log('我会唱歌');
  // }
}
Star.prototype.sing = function (){
  console.log('我会唱歌');
}
let ldh = new Star('刘德华', 18)
let zxy = new Star('张学友', 2)
console.log(ldh.sing === zxy.sing); // true

1.原型是什么?
一个对象,我们也称为 prototype为原型对象

2.原型的作用是什么
共享方法

总结: 一般情況下,我们的公共属性定义到构造函数里面,公共的方法我们放到原型对象身上

对象原型

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
}
Star.prototype.sing = function (){
  console.log('我会唱歌');
}

let ldh = new Star('刘德华', 18)

对象都会有一个属性 proto 指向构造函数的 prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有 proto際型的存在。

console.log(Star.prototype === ldh.__proto__); //true
console.log(Star.prototype.sing === ldh.__proto__.sing);//
console.log(ldh.sing === ldh.__proto__.sing);//true

个人总结就是:实例对象的 proto 指向(等于) 构造函数的 prototype

注意,方法的查找规则:

  1. 首先先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing
  2. 如果没有sing这个方法,因为有 proto的存在,就去构造函数原型对象 prototype身上去查找sing这个方法
    在这里插入图片描述

原型的 constructor构造函数

对象原型(proto)和构造函数( prototype)原型对象里面都有一个属性 constructor属性, constructor我们称为构造函数,因为它指回构造函数本身。

constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

重新指回原来的构造函数:

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
}

 Star.prototype = {
   // 手动指回原来的构造函数
   constructor: Star,
   sing: function () {
     console.log('我会唱歌');
   },
   movie: function () {
     console.log("我会演电影");
   },
 }
 let ldh = new Star('刘德华', 18)
console.log(ldh.constructor === ldh.__proto__.constructor); // true
console.log(ldh.constructor === Star.prototype.constructor); // true

铁三角:
在这里插入图片描述

在这里插入图片描述

原型链

在这里插入图片描述
示例:

function Star(uname, age) {
  this.uname = uname;
  this.age = age;
}
// prototype是一个对象,默认是带有constructor的,但是使用赋值操作后把对象覆盖了
Star.prototype = {
  // 手动指回原来的构造函数
  constructor: Star,
  sing: function () {
    console.log('我会唱歌');
  },
  movie: function () {
    console.log("我会演电影");
  },
}
//1.只要是对象就有 proto_原型,指向原型对象
console.log(Star.prototype.__proto__ === Object.prototype); //true
//2.我们Star原型对象里面的_ proto_原型指向的是 object. prototype
// 3. 我们Object.prototype原型对象里边的 __proto__原型 指向 null
console.log(Object.prototype.__proto__); // null

Object.prototype.gogo = function (){
  console.log("gogo");
}
let ldh = new Star("刘德华",18)
console.log(ldh.__proto__.__proto__.gogo === Object.prototype.gogo); // true

object就是所有类的父类,上面没有了

原型对象的应用

// 原型对象的应用 扩展内置对象方法
Array.prototype.sum = function () {
  let sum = 0
  for (let i = 0; i < this.length; i++) {
    sum += this[i]
  }
  return sum
}
console.log(Array.prototype);
let arr = [1,2,3,4,5,6,7,8,9]
console.log(arr.sum());//45

注意:数组和字符串内置对象不能给原型对象覆盖操作
Array prototype = {…} //错误示例
只能是
Array.prototype.xxx= function(){…}
的方式

总结

  • 构造函数有原型对象 prototype
  • 构造函数原型对象 prototype里面有 constructor指向构造函数本身
  • 构造函数可以通过原型对象添加方法
  • 构造函数创建的实例对象有 __proto__原型指向构造函数的原型对象

5.21 选项卡-面向对象

        <style>
            #div1 input {
                background: white;
            }
            #div1 input.active {
                background: yellow;
            }
            #div1 div {
                width: 200px;
                height: 200px;
                background: #ccc;
                display: none;
            }
        </style>
        <script>
            window.onload = function() {
                //创建一个选项卡对象,在某一个div中
                new Tabswitch('div1');
            }
            function Tabswitch(id) {
                var _this = this;
                var oDiv = document.getElementById(id);
                //定义选项卡的两个属性,分别为上面的选择器和下面的显示内容
                this.aBtn = oDiv.getElementsByTagName('input');
                this.aDiv = oDiv.getElementsByTagName('div');
                //循环初始化选项卡的各个选择按钮
                //初始化两个地方,1是选项卡的index属性,另一个为选项卡的方法
                for(var i = 0; i < this.aBtn.length; i++) {
                    this.aBtn[i].index = i;
                    this.aBtn[i].onclick = function() {
                        _this.fnClick(this);
                    };
                }
            }
            //统一定义点击选项卡之后的方法
            Tabswitch.prototype.fnClick = function(oBtn) {
                //              将所有的选项卡状态还原
                for(var i = 0; i < this.aBtn.length; i++) {
                    this.aBtn[i].className = '';
                    this.aDiv[i].style.display = 'none';
                }
                //选择,并操作
                oBtn.classname = 'active';
                this.aDiv[oBtn.index].style.display = 'block';
            }
        </script>



        <div id="div1">
            <input class="active" type="button" value="aaa" />
            <input type="button" value="bbb" />
            <input type="button" value="ccc" />
            <div style="display: block;">aaa</div>
            <div>afdafje</div>
            <div>afjeiofje</div>
        </div>

5.22 ES6的class

在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。

class 的本质是 function。

它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。

5.22.1constructor 方法

constructor 方法是类的默认方法,创建类的实例化对象时被调用。

    <script>
        class CreateObj{
            //构造函数
            constructor(name){
                this.name = name
            }
            say(){
                console.log(this.name,"hello")
            }
        }
        var obj = new CreateObj("steve")
        console.log(obj)
        obj.say()     
    </script>

在这里插入图片描述

5.23 面向对象的继承

5.23.1 构造函数继承

原理:子类的构造函数中执行父类的构造函数,并为其绑定子类的 this,让父类的构造函数把成员属性和方法都挂到子类的 this 上去,这样既能避免实例之间共享一个原型实例,又能向父类构造方法传参
1。

function Student (name,age ,classroom) {
Person. call(this, name ,age)
this. classroom = class room
}
function Parent(name) {
    this.name = name
}
Parent.prototype.getName = function () {
    return this.name
}
function Child() {
    // 执行父类的构造函数,并修改 this 指向到子类, 使得父类中的属性能够赋到子类的 this 上
    Parent.call(this, 'huohuo') // 既能避免实例之间共享一个原型实例,又能向父类构造方法传参
}
const child1 = new Child()
console.log(child1.name) // huohuo
child1.getName() // 报错, 找不到getName(), 构造函数继承的方式继承不到父类原型上的方法             

解决了原型继承中“引用类型私有属性变公有”、“不可传递参数”两个问题

缺点:继承不到父类原型上的方法(所以不能单独使用咯 ~)

5.23.2 原型继承

原理:让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承

Student . prototype = new Person()
// 父类
function Parent() {
    this.name = 'huohuo'
}
// 在父类原型上添加方法
Parent.prototype.getName = function () {
    return this.name
}
// 子类
function Child() { }
 
// 继承 Parent
Child.prototype = new Parent() // 让子类的原型对象指向父类实例, 这样一来在Child实例中找不到的属性和方法就会到原型对象(父类实例)上寻找
// 解决重写原型导致的 constructor 丢失问题(增强对象)
Child.prototype.constructor = Child // 根据原型链的规则,顺便绑定一下constructor, 这一步不影响继承, 只是在用到constructor时会需要
// 创建一个实例化对象
const child = new Child() // 然后 Child实例 就能访问到父类及其原型上的 name属性 和 getName方法
child.name          // 'huohuo'
child.getName()     // 'huohuo'

缺点:

  • 由于所有Child实例原型都指向同一个Parent实例,引用类型的私有属性公有化了,
    因此对某个Child实例的父类引用类型做变量修改会影响所有的Child实例
  • 在创建子类实例时无法向父类的构造函数传参(没有 super 功能)

5.23.3 组合继承

原理:使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性(构造函数+原型对象

function Parent (name) {
    this.name = name
}
Parent.prototype.getName = function () {
    return this.name
}
function Child () {
    // 构造函数继承
    Parent.call(this, 'huohuo') // 既能避免实例之间共享一个原型实例,又能向父类构造方法传参
}
//原型链继承
Child.prototype = new Parent() // 父类的方法可以被子类通过原型拿到
Child.prototype.constructor = Child // 顺带绑定下 constructor (增强对象)
 
//测试
const child1 = new Child()
const child2 = new Child()
child1.name = 'foo'
console.log(child1.name)          // foo
console.log(child2.name)          // huohuo
child2.getName()                  // 'huohuo'
  • 组合式继承的缺点:每次创建子类实例都执行了两次构造函数(Parent.call() 和 new Paren()),虽然这并不影响对父类的继承,但子类创建实例时,原型中会存在两份相同的属性和方法,这并不优雅

5.24 初识前后端交互

在这里插入图片描述

5.25 ajax

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。 AJAX 不是新的编程语言,而是一种使用现有标准的新方法。 AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。

认识AJAX:

  1. AJAX即“Asynchronous Javascript And
    XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
  2. AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。
  3. AJAX 是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。

5.25.1 AJAX的优势

1.不需要插件的支持,原生js就可以使用
2.用户体验好(不需要刷新页面就可以更新数据)
3.减轻服务端和带宽的负担
4.缺点:搜索引擎的支持度不够,因为数据都不在页面上,搜索引擎搜索不到

5.25.2 AJAX的使用

●在js中有内置的构造函数来创建ajax对象
●创建ajax对象以后,我们就使用ajax对象的方法去发送请求和接受响应

1.创建一个ajax对象
在这里插入图片描述
2.配置链接信息

const xhr = new XMLHttpRequestO
// xhr 对象中的 open方法是来配置请求信息的
// 第一个参数是 本次请求的请求方式get / post / put / ...
//第二个参数是本次请求的ur1
// 第三个参数是本次请求是否异步, 默认true 表示异步, false表示同步
// xhr. open('请求方式’,'请求地址’, 是否异步)
xhr . open(' get','. /data. php')
  • 上面的代码执行完毕以后,本次请求的基本配置信息就写完了

3.发送请求

const xhr = new XMLHttpRequest()
xhr . open(' get', ' ./data. php')
//使用xhr对象中的send 方法来发送请求
xhr. send(
  • 上面代码是把配置好信息的ajax对象发送到服务端

案例:

    <body>
    <form action="1-1-1.php" method="get">
        <input type="text" name="names" value=""><br>
        <input type="button" value="提交">
    </form>
</body>
<script>
    //获取DOM对象
    var inp = document.getElementsByTagName('input');
    //绑定点击事件
    inp[1].onclick = function(){
        //获取文本值
        var v = inp[0].value;
        //获取ajax对象
        var xhr = new XMLHttpRequest();
        //监听状态变化
        xhr.onreadystatechange = function(){
            //判断状态值
            if(xhr.readyState == 4){
                //获取服务器返回信息
                alert(xhr.responseText);
            }
        }
        //打开链接
        xhr.open('get','1-1-2.php');
        //发送连接
        xhr.send();
    }
</script>

5.25.3 一个基本的ajax请求

  • 一个最基本的ajax请求就是上面三步
  • 但是光有上面的三个步骤,我们确实能把请求发送的到服务端
  • 如果服务端正常的话,响应也能回到客户端
  • 但是我们拿不到响应
  • 如果想拿到响应,我们有两个前提条件
  1. 本次HTTP请求是成功的,也就是我们之前说的http状态码为200 ~ 299
  2. ajax对象也有自己的状态码,用来表示本次ajax请求中各个阶段

5.25.4 ajax 状态码

  • ajax状态码- xhr. readyState
  • 是用来表示一个ajax请求的全部过程中的某一个状态
  • 。 readystate === 0:表示未初始化完成,也就是open方法还没有执行
  • 。readystate === 1: 表示配置信息已经完成,也就是执行完open之后
  • 。readystate === 2: 表示send方法已经执行完成
  • 。readystate === 3: 表示正在解析响应内容
  • 。readystate === 4:表示响应内容已经解析完毕,可以在客户端使用了
  • 这个时候我们就会发现,当-个ajax请求的全部过程中,只有当readystate === 4的时候,我们才可以正常使用服务端给我们的数据
  • 所以,配合http状态码为200 ~ 299
  • 。一个ajax对象中有一个成员叫做xhr. status
  • 。这个成吊就是记录太次请求的http状太码的
  • 两个条件都满足的时候,才是本次请求正常完成

5.25.5 readyStateChange

  • 在ajax对象中有一个事件,叫做readystateChange 事件
  • 这个事件是专门用来监听ajax对象的readyState 值改变的的行为
  • 也就是说只要readystate 的值发生变化了,那么就会触发该事件
  • 所以我们就在这个事件中来监听ajax的readystate 是不是到4了
const xhr = new XMLHttpRequest()
xhr. open('get', ' . /data. php')
xhr . send()
xhr. onreadystateChange = function () {
//每次readystate 改变的时候都会触发该事件
//我们就在这里判断readystate 的值是不是到4
//并且http 的状态码是不是200 ~ 299
if (xhr. readyState === 4 && /^2\d{2|$/. test(xhr. status)) {
//这里表示验证通过
//我们就可以获取服务端给我们响应的内容了
}
}

5.26 ajax 同步异步

    <script>
        var xhr = new XMLHttpRequest()
        xhr.open("GET", "1.json", true)
        //true 表示异步请求
        //false表示同步请求
        xhr.onload = function () {
            if (xhr.status === 200) {
                console.log(xhr.responseText)
            }
        }
        xhr.send()

        console.log("1111111111111111111")
    </script>

在这里插入图片描述

5.27 ajax的请求方式

5.27.1 $.ajax()返回其创建的 XMLHttpRequest 对象

$.ajax() 只有一个参数:参数key/value对象,包含各配置及回调函数信息。

如果你指定了dataType选项,那么需要保证服务器返回正确的MIME信息,(如 xml 返回 “text/xml”)。

实例:
保存数据到服务器,成功时显示信息。

$.ajax({
type: "post",
dataType: "html",
url: '/Resources/GetList.ashx',
data: dataurl,
success: function (data) {
if (data != "") {
$("#pager").pager({ pagenumber: pagenumber, pagecount: data.split("$")[1], buttonClickCallback: PageClick });
$("#anhtml").html(data.split("$")[0]);
}
}
});

5.27.2 通过远程 HTTP GET 请求载入信息

相比于复杂的$.ajax而言,GET请求功能则显得更加简单,
请求成功时可调用回调函数。当然如果需要在出错时执行函数,
那么还请使用$.ajax。

实例:

$.get("test.cgi", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});

5.27.3 通过远程 HTTP POST 请求载入信息

POST请求功能也相对比较简单,请求成功时可调用回调函数。如果需要在出错时执行函数,那么请使用$.ajax请求。
 实例:

$.post("/Resources/addfriend.ashx", { "fid": fids, "fname": fnames, "tuid": tuids, "tuname": tunames }, function (data) {
if (data == "ok") {
alert("添加成功!");
}
})

5.27.4 通过 HTTP GET 请求载入 JSON 数据

实例:

$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
function(data){
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});

5.28 ajax的封装

5.28.1ajax的get 请求

  • 步骤:
    1、创建xhr
    2、监听xhr.onreadystatechange事件 ajax状态发生变化的事件
    3、判断ajax请求的状态
    4、设置请求方式和url
    5、发送请求
<script>
        //使用xhr对象发送get方式请求
        //   创建xhr
        let xhr = new XMLHttpRequest();
        // 监听xhr.onreadystatechange事件 ajax状态发生变化的事件
        xhr.onreadystatechange = function () {
            // 固定写法 readyState 表示 ajax的状态 
            //ajax的状态总共有(0 1 2 3 4 )五种状态 状态为4表示请求完成 status === 200表示成功
            if (xhr.readyState == 4 && xhr.status === 200) {
                // xhr.responseText;  // 接收响应结果
                let res = xhr.responseText;  // 结果是JSON字符串
                // 转化为数组对象
                JSON.parse(res)
            }
        }
        // 调用xhr.open()函数 设置请求方式和url
        // 查询字符串的写法 key=value&key=value....  字符串和接口之间用?隔开
        xhr.open('GET', '接口文档url地址')
        // 调用xhr.send()函数 发送请求
        xhr.send()
    </script>

5.28.2 ajax 的post请求

  • 步骤:
    1、创建xhr
    2、监听xhr.onreadystatechange事件 ajax状态发生变化的事件
    3、判断ajax请求的状态
    4、设置请求方式和url
    5、告诉服务器请求头(前端提交的是什么类型数据)
    6、发送请求
 <script>
        // 创建xhr对象
        let xhr = new XMLHttpRequest();
        // 注册事件
        xhr.onreadystatechange = function () {
            if (this.readyState === 4 && this.status === 200) {
                let res = JSON.parse(this.responseText)
            }
        }
        // 调用open 设置请求方式和url
        xhr.open('POST', '接口文档url地址');
        // 请求头 必须写在open和send之间
        // 告诉服务器 前端提交数据是什么类型  表示查询字符串类型
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        // send里面写 查询字符串 格式:key=value&key=value....
        xhr.send('查询字符串')
    </script>

5.28.3 封装ajax 请求

步骤:

  1. 第一大步:
    1、创建xhr
    2、监听xhr.onreadystatechange事件 ajax状态发生变化的事件
    3、判断ajax请求的状态
    4、接受响应结果 并且转为数组对象形式
    5、调用参数里面的 success函数

  2. 第二大步:
    1、处理参数中data数据 遍历对象
    2、将data数据转为查询字符串
    3、判断请求方式时 get 还是 post 并 设置请求方式 发送请求

  3. 第三大步:
    调用封装的函数 并且 传参

 <script>
  // 封装一个函数
        function ajax(option) {
            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (this.readyState === 4 && this.status === 200) {
                    let res = JOSN.parse(this.responseText);
                    option.success(res)   //这里调用success函数  
                }
            };
            // 处理data数据  将对象形式的 处理查询字符串形式的  
            // 因为下面open 或者 send只能加字符串形式 
            let arr = []
            for (let i in option.data) {
                // i表示对象的key
                // option.data[i]表示对象的值
                arr.push(i + '=' + option.data[i]);  // ['bookname=aaa', 'author=bbb', ...]
            }
            //join() 把数组转化为字符串,元素是通过指定的分隔符进行分隔的,如果没有默认为逗号
            let querystring = arr.join('&');  // bookname=aaa&author=bbb&publiser=ccc

            // toUpperCase()  转大写
            let method = option.type.toUpperCase(); // 把请求方式转成大写   识别 post / POST
            //  判断请求
            if (option.type === 'GET') {
                xhr.open('GET', option.url + '?' + querystring);
                xhr.send();
            } else if (option.type === 'POST') {
                xhr.open('POST', option.url);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
                xhr.send(querystring);
            }
        };
        
	   //调用  传参 数数就是数据
        ajax({
            type: 'GET',  //或者 ‘post’
            url: '接口文档 url地址,
            data: {数据,根据接口文档提供属性},
            success: function (res) {}
        });
    </script>

5.29 回调地狱问题

回调地狱
将函数作为参数传入,一个嵌套着一个,到最后代码排列成了 一个三角形, 造成了可阅读性差,代表代码的可维护性 差、可迭代性差、可扩展性差。

回调函数
回调函数不是由该函数的实现而直接调用的,而是在特定的事件或条件发生时由另外的一方法调用执行的,用于对该事件或条件进行响应。

  • 当一个回调函数嵌套一个回调函数的时候
  • 就会出现一个嵌套结构
  • 当嵌套的多了就会出现回调地狱的情况
  • 比如我们发送三个ajax请求

。第一个正常发送
。第二个请求需要第一个请求的结果中的某一 个值作为参数
。第三个请求需要第二个请求的结果中的某- 个值作为参数

案例:

//ajax通过get方法获取json数据

// 参数     过去数据的地址  即json文件的地址 
// 目标属性名  目标值   通过此属性名 获取相应的数据 同属性值进行判断  
//  从而获取相应的结果
// 回调函数参数
function find(url,targetName,target,result,callback){
// 通过简写的ajax 的get方法来进行数据的获取
    $.get(url, (data) => {
    //判断目标
       for(let i = 0; i<data.length;i++){
           if(data[i][targetName] == target){
           // 将查找到的结果作为函数的参数进行回调 
               if(data[i][result]){
                   callback(data[i][targetName],data[i][result])
                   break;
                }
            }  
       }
    })
}
// 回调地狱
// 查找 id = 5 的学生的姓名 分数
find("data.json","id","5","name",function(target,result){
    find("data2.json","name",result,"score",function(target,result){
            console.log(`${target}同学分数为${result}`)
    })
})
//在此数据较少的情况下,呈现的效果不明显,当数据量庞大后,代码三角的特性还是很明显的,这样的代码可读性差,后期的维护也麻烦,但是回调的思想是会经常用到的,所以可以采取其他的方法解决回调地狱可读性差等缺陷问题

5.30 Promise 基础语法

  • promise是一一个ES6的语法
  • 承诺的意思,是一个专门用来解决异步回调地狱的问题

5.30.1 Promise的状态

promise有三种状态:

  1. pending (初始化状态)
  2. fulfilled (成功)
  3. rejected (失败)

Promise对象的状态改变,只有两种可能:从pending变为resolved、从pending变为rejected,之后状态不会在改变了且状态不可逆。

语法:

new Promise(function (resolve, reject) {
// resolve 表示成功的回调
// reject 表示失败的回调
}). then(function (res) {
// 成功的函数
}). catch(function (err) {
// 失败的函数
})

5.30.2 resolve reject

1.new Promise 实例 要return
2.传入函数 要有resolve reject 俩参数
3.成功执行resolve 失败 reject
4.then 监听结果并且接收结果

不使用Promise的话模拟一个callback Hell

function loadImg(src, callback, fail){
  var img = document.createElement('img')
  img.onload = function () {
    callback(img)
  }
  img.onerror = function () {
    fail()
  }
  img.src = src
}
var src = 'www.s.com/index/logo.png'

loadImg(src, function (img) {
  console.log(img.width)// callback Hell 我们还要做好多事情 这样看的就很不友好
}, function () {
  console.log('failed')
})

使用Promise

function loadImg(src) {
  const promise = new Promise(function(resolve,reject){
    img.onload = function () {
      resolve(img)
    }
    img.onerror = function () {
      reject()
    }
    img.src = src
  })
  return promise
}
var src = ''

var result = loadImg(src)
result.then()
result.then()

5.30.3 catch捕获

catch通常用于最后统一捕获,我我们try catch一样

Error和eject都可以捕获

result.then(function(img){
      // dosomthing
    }).then(function(){
      // dosomthing
    }).catch(function(error){
      console.log(error)
    })

5.30.4 多个串联

如果我们希望我们的需求按顺序加载(例如,先加载用户信息,然后再通过用户信息渲染好友列表之类的)
我们需要在.then之后return 另外一个Promise 就可以了

var src1 = 'www.xxx.com/1.jpg'
var src2 = 'www.xxx.com/2.jpg'
var img1 = loadImg(src1)
var img2 = loadImg(src2)

//链式操作
img1.then(function(img){
  console.log('图片一加载完成', img)
  return img2 //接下来就是对img2进行异步操作了
}).then(function(img){
  console.log('图片二加载完成', img)
}).catch(function(er){
  console.log(er)
})

5.30.5 Promise.all

Promise.all 接收一个Promose对象数组 待全部完成之后 一起执行success。(有点像JS中短路操作的 且&&)

.then方法接收的datas是一个数组,依次包含多个Promise返回值

Promise.all([result1,result2]).then(datas => {
  console.log(datas[0])
  console.log(datas[1])
})

5.30.6 Promise.race

和all不一样的是 数组中只要有一个完成 就执行success
(参考JS短路操作的 或||)

Promise.race([result1,result2]).then(data => {
  console.log(data)
})

5.31 Promise封装ajax

function ajax(options) {
  //这个options时传入给ajax的配置参数
  return new Promise((resolve, reject) => {
    //返回一个promise对象 resolve成功是的处理,reject失败时的处理
    if (!options.url) { // 需要请求的路径
      console.log("请确认你的url路径");
      return;
    }
    let method = options.method || "GET"; //请求方式如果没有就默认为get
    let async = options.async || true; //ajax是否异步请求默认位true
    let xhr = new XMLHttpRequest();
    if (method === "GET") {
      xhr.open(method, options.url + "?" + Math.random(), async); //防止缓存
      xhr.send(null);
    } else if (method === "POST") {
      xhr.open(method, options.url, async);
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xhr.send(options.data);
    }
    // xhr.responseType = options.type || "";

    xhr.onreadystatechange = () => {
      if (xhr.responseText) {
        //有数据说明相应成功
        resolve(xhr.responseText);
      }
    };
    xhr.onerror = err => {
      reject(err);
    };
  }).catch(e => {});
}

5.32 async和await语法

async/await是一个es7的语法
这个语法是回调地狱的终极解决方案
语法:

async function fn() {
const res = await promise 对象
}
  • 这个是一个特殊的函数方式
  • 可以await 一个promise对象
  • 可以把异步代码写的看起来像同步代码
  • 只要是一一个promiser对象,那么我们就可以使用async/await来书写

5.32.1 async

async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async函数可以直接then,返回值就是then方法传入的函数。

// async基础语法
async function fun0(){
    console.log(1);
    return 1;
}
fun0().then(val=>{
    console.log(val) // 1,1
})

async function fun1(){
    console.log('Promise');
    return new Promise(function(resolve,reject){
        resolve('Promise')
    })
}
fun1().then(val => {
    console.log(val); // Promise Promise
})

5.32.2 await

  • await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。

    await
    修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;

    如果不是Promise对象:把这个非promise的东西当做await表达式的结果。

案例:

async function fun(){
    let a = await 1;
    let b = await new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('setTimeout')
        },3000)
    })
    let c = await function(){
        return 'function'
    }()
    console.log(a,b,c)
}
fun(); // 3秒后输出: 1 "setTimeout" "function"

function log(time){
    setTimeout(function(){
        console.log(time);
        return 1;
    },time)
}
async function fun(){
    let a = await log(1000);
    let b = await log(3000);
    let c = log(2000);
    console.log(a);
    console.log(1)
}
fun(); 
// 立即输出 undefined 1
// 1秒后输出 1000
// 2秒后输出 2000
// 3秒后输出 3000

async/await 的正确用法:

// 使用async/await获取成功的结果

// 定义一个异步函数,3秒后才能获取到值(类似操作数据库)
function getSomeThing(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('获取成功')
        },3000)
    })
}

async function test(){
    let a = await getSomeThing();
    console.log(a)
}
test(); // 3秒后输出:获取成功

5.33 fetch

XMLHttpRequest是一个设计粗糙的API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好。
兼容性不好polyfill: https://github.com/camsong/fetch-ie8

Fetch API提供了一个 JavaScript 接口,用于访问和操纵HTTP的请求和响应等。提供了一个全局 fetch()方法来跨网络异步获取资源。

fetch与ajax的区别:

1、fetch没有办法原生监测请求的进度,而ajax基于原生的XHR开发,可以监测;
2、和ajax相比,fetch有着更好更方便的写法;
3、fetch只对网络请求报错,对400、500都当做成功的请求,而ajax不会。

5.33.1 fetch示例

给fetch() 提供一个参数指明资源路径,会返回一个包含响应结果的promise。当然它只是一个 HTTP 响应,为了获取JSON的内容,我们需要使用 json() 方法:
默认发送GET请求

fetch('http://example.com/movies.json')	
  .then(response => response.json())
  .then(data => console.log(data));

带参数的GET请求:

var id=1
fetch(`https://www.easy-mock.com/mock/5f507e38a758c95f67d6eb42/fetch/getmsg?id=${id}`)	
.then(response => response.json())
.then(data => console.log(data));

发送POST请求

var data={
    id:'1',
}
fetch('https://www.easy-mock.com/mock/5f507e38a758c95f67d6eb42/fetch/postmsg',{
    method:'POST',
    body:data
})	
.then(response => response.json())
.then(data => console.log(data));

5.33.2 Fetch()语法

fetch(input,{init});

input——定义要获取的资源,可以是:

  • 一个 USVString 字符串,包含要获取资源的 URL。
  • 一个 Request 对象。

5.34 cookie

什么是 Cookie
Cookie 是一些数据, 存储于你电脑上的文本文件中。

当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。

Cookie 的作用就是用于解决 “如何记录客户端的用户信息”:

  • 当用户访问 web 页面时,他的名字可以记录在 cookie 中。
  • 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。

Cookie 以名/值对形式存储,如下所示:

username=John Doe

当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。

5.34.1 JavaScript 创建Cookie

JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie。

JavaScript 中,创建 cookie 如下所示:

document.cookie="username=John Doe";

还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";

可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

5.34.2 JavaScript 读取 Cookie

在 JavaScript 中, 可以使用以下代码来读取 cookie:

var x = document.cookie;

document.cookie 将以字符串的方式返回所有的 cookie,类型格式: cookie1=value;
cookie2=value; cookie3=value;

5.34.3 JavaScript 修改 Cookie

在 JavaScript 中,修改 cookie 类似于创建 cookie,如下所示:

document.cookie="username=John Smith; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

旧的 cookie 将被覆盖。

5.34.4 JavaScript 删除 Cookie

删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

注意,当您删除时不必指定 cookie 的值。

5.34.5 Cookie 字符串

document.cookie 属性看起来像一个普通的文本字符串,其实它不是。

即使在 document.cookie 中写入一个完整的 cookie 字符串, 当您重新读取该 cookie 信息时,cookie 信息是以名/值对的形式展示的。

如果设置了新的 cookie,旧的 cookie 不会被覆盖。 新 cookie 将添加到 document.cookie
中,所以如果您重新读取document.cookie,您将获得如下所示的数据:

cookie1=value; cookie2=value;
document.cookie 属性看起来像一个普通的文本字符串,其实它不是。

即使在 document.cookie 中写入一个完整的 cookie 字符串, 当您重新读取该 cookie 信息时,cookie 信息是以名/值对的形式展示的。

如果设置了新的 cookie,旧的 cookie 不会被覆盖。 新 cookie 将添加到 document.cookie
中,所以如果重新读取document.cookie,将获得如下所示的数据:
cookie1=value; cookie2=value;

5.34.6 JavaScript Cookie 实例

在以下实例中,我们将创建 cookie 来存储访问者名称。

首先,访问者访问 web 页面, 他将被要求填写自己的名字。该名字会存储在 cookie 中。

访问者下一次访问页面时,他会看到一个欢迎的消息。

在这个实例中我们会创建 3 个 JavaScript 函数:

  1. 设置 cookie 值的函数
  2. 获取 cookie 值的函数
  3. 检测 cookie 值的函数

5.35 jsonp

JjsonpISON With Padding)是json的一-种使用模式",可以让网页从别的域名(网站) 那获取资料,即跨域读取
数据。
为什么我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )呢?这是因为同源策略。

在这里插入图片描述

const script = document. createElement('script')
script.src = ' . /kerwin. txt'
document . body. appendChild(scri pt)

注意:
1.后端接口形式必须**() ,需要后端配合
2. jsonp 缺点
(1) onload 删除sciprt标签
(2)只能get请求, 不能post put delete

5.36 jsonp的应用

5.36.1 服务端 JSONP 格式数据

如客户想访问 : https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction。

假设客户期望返回数据:[“customername1”,“customername2”]。

真正返回到客户端的数据显示为: callbackFunction([“customername1”,“customername2”])。

服务端文件 jsonp.php 代码为:

<?php
header('Content-type: application/json');
//获取回调函数名
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json数据
$json_data = '["customername1","customername2"]';
//输出jsonp格式的数据
echo $jsoncallback . "(" . $json_data . ")";
?>

5.36.2 客户端实现 callbackFunction 函数

function callbackFunction(result, methodName)
{
    var html = '<ul>';
    for(var i = 0; i < result.length; i++)
    {
        html += '<li>' + result[i] + '</li>';
    }
    html += '</ul>';
    document.getElementById('divCustomers').innerHTML = html;
}

5.37 再谈函数

函数有返回值,而且返回值必须是复杂类型,而且要赋值给外面的变量。

function test(){
var name ="kerwin"
console.log(name)
var obj = {
a:1,
b:2
return obj
}
var obj1 = test()

var obj2=test()

在这里插入图片描述

5.38 闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。

function FetchContainer(url){
return function(path){
return fetch(url+path)
var fetcha = FetchContainer("http://www.a.com")
fetcha("/aaa").then(res=>res.json()).then(res=>console.log(res))
fetcha("/bbb").then(res=>res.json()).then(res=>console.log(res))
fetcha =null
这样子蟹后面可以加而且
回收和方便
不用就回收

输入后才请求发送

mysearch.oninput =(function (){
var timer
null
return function () {
if (timer) {
clearTimeout(timer)
timer = setTimeout(function () {
console.log("发ajax请求"},500)
})()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值