• Vue、js底层深入理解笔记(二)


    1.跨域

    跨域原因 => 浏览器的同源策略 属于一种保护机制

    如果没有同源策略的保护
    一般用来处理登录cookie、服务端验证通过后会在响应头加入Set-Cookie字段、下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中、也就是说跳转到其他网站你也是携带Cookie过去的、就相当于你的账号被别人登录了、对方还能使用iframe获取dom节点进而获取你的账号密码

    我们如何解决跨域

    1. JSONP 只支持get请求

    前后端协商名称

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
      </head>
      <body>
        <script type='text/javascript'>
          // 后端返回直接执行的方法,相当于执行这个方法,由于后端把返回的数据放在方法的参数里,所以这里能拿到res。
          window.jsonpCb = function (res) {
            console.log(res)
          }
        </script>
        <script src='http://localhost:xxxx/api/jsonp?msg=helloJsonp&cb=jsonpCb' type='text/javascript'></script>
      </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    /**
     * JSONP请求工具
     * @param url 请求的地址
     * @param data 请求的参数
     * @returns {Promise}
     */
    const request = ({url, data}) => {
      return new Promise((resolve, reject) => {
        // 处理传参成xx=yy&aa=bb的形式
        const handleData = (data) => {
          const keys = Object.keys(data)
          const keysLen = keys.length
          return keys.reduce((pre, cur, index) => {
            const value = data[cur]
            const flag = index !== keysLen - 1 ? '&' : ''
            return `${pre}${cur}=${value}${flag}`
          }, '')
        }
        // 动态创建script标签
        const script = document.createElement('script')
        // 接口返回的数据获取
        window.jsonpCb = (res) => {
          document.body.removeChild(script)
          delete window.jsonpCb
          resolve(res)
        }
        script.src = `${url}?${handleData(data)}&cb=jsonpCb`
        document.body.appendChild(script)
      })
    }
    // 使用方式
    request({
      url: 'http://localhost:xxxx/api/jsonp',
      data: {
        // 传参
        msg: 'helloJsonp'
      }
    }).then(res => {
      console.log(res)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    1. 空iframe加form
    const requestPost = ({url, data}) => {
      // 首先创建一个用来发送数据的iframe.
      const iframe = document.createElement('iframe')
      iframe.name = 'iframePost'
      iframe.style.display = 'none'
      document.body.appendChild(iframe)
      const form = document.createElement('form')
      const node = document.createElement('input')
      // 注册iframe的load事件处理程序,如果你需要在响应返回时执行一些操作的话.
      iframe.addEventListener('load', function () {
        console.log('post success')
      })
    
      form.action = url
      // 在指定的iframe中执行form
      form.target = iframe.name
      form.method = 'post'
      for (let name in data) {
        node.name = name
        node.value = data[name].toString()
        form.appendChild(node.cloneNode())
      }
      // 表单元素需要添加到主文档中.
      form.style.display = 'none'
      document.body.appendChild(form)
      form.submit()
    
      // 表单提交后,就可以删除这个表单,不影响下次的数据发送.
      document.body.removeChild(form)
    }
    // 使用方式
    requestPost({
      url: 'http://localhost:xxxx/api/iframePost',
      data: {
        msg: 'helloIframePost'
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    3.CORS
    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
    浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

    只要同时满足以下两大条件,就属于简单请求。
    在这里插入图片描述

    参考文章地址

    4.代理
    Nginx conf配置

    server{
        # 监听9099端口
        listen 9099;
        # 域名是localhost
        server_name localhost;
        #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
        location ^~ /api {
            proxy_pass http://localhost:9871;
        }    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    参考链接地址


    2. 继承

    1. 继承首先想到的是原型链继承
     //例
     // 原型链继承
      function Super(){
        this.color=['red','yellow','black']
      }
    
      function Sub(){
      }
      //继承了color属性 Sub.prototype.color=['red','yellow','black']
      Sub.prototype=new Super()
    
      //创建实例 instance1.__proto__.color
      const instance1=new Sub()
      const instance2=new Sub()
      console.log(instance1.__proto__.color===instance2.__proto__.color) //true
    
    
    # new XXX()就相当于创建一个函数data XXX()里的代码指向这个data并执行一遍
    
    例如 
      function AAA(){
        this.color=['red','yellow','black']
      }
     let a=new AAA()  ==>  let a={},  a.color=['red','yellow','black']
     
    ==由此得出结论原型链继承缺点 实例之间共用一个值、而且无法向构造函数Super传递值==
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    1. 构造函数继承
      function Super(name,age){
        this.name=name
        this.age=age
        this.color=['red','yellow','black']
        this.sayHi=function(){
          console.log('hi',this)
        }
      }
      function Sub(){
        Super.apply(this,arguments)
        this.height=180
        //这里的apply就相当new了一下Super
        //this.name=name
        //this.age=age
        //this.color=['red','yellow','black']
        //this.sayHi=function(){
        //  console.log('hi',this)
        //}
      }
      //创建实例 
      var instance1=new Sub('xiaobai',18)
      var instance2=new Sub('xiaohei',20)
      instance1.sayHi()
      
      ==方法只能定义在构造函数中,函数无法复用==
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    1. 组合继承
    function Super(name,age){
        this.name=name
        this.age=age
        this.color=['red','yellow','black']
      }
     Super.prototype.sayHi=function(){
        console.log('hi')
      }
     function Sub(name,age,height){
        //继承属性
        Super.apply(this,arguments)
        this.height=height
      }
      // 继承方法(重写子类原型对象)
      //1.通过原型链继承了方法:Sub.prototype.__proto__===Super.prototype
      //2.Sub.prototype:{name: undefined, age: undefined, color: Array(3)}
      //3.Sub原型对象已经被覆盖,现在只能从原型链上找constructor,指向Super
      Sub.prototype=new Super()
     //constructor重新指向Sub
      Sub.prototype.constructor=Sub
      console.log(Sub.prototype)//{name: undefined, age: undefined, color: Array(3), constructor: ƒ}
      // 定义属于子类的方法
      Sub.prototype.sayHello=function(){
        console.log('sayHello')
      }
    
      //创建实例 
      var instance1=new Sub('xiaobai',25,180)
      var instance2=new Sub('xiaohei',24,170)
     
      console.log(instance1)
      
    == 通过构造函数让实例拥有属于自己的属性(name,age,color等),不会相互影响、通过原型链继承了父类的方法,实现了函数复用==
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    1. 原型式继承
     function object(o){
        function F(){}
        //F.prototype={name:'ccdida',friends:['shelly','Bob']}
        F.prototype=o
        // new F() 
        //F是个构造函数,返回F的实例:1.this此时用不上 2.将实例的__proto__指向F.prototype.
        //即返回了一个实例,其__proto__指向{name:'ccdida',friends:['shelly','Bob']}
        return new F()
      }
      var person={
        name:'ccdida',
        friends:['shelly','Bob']
      }
      var person1=object(person)
      var person2=object(person)
      //object函数相当于实现了Object.Create的功能
      console.log(person1.__proto__===person) //true 
      person2.friends.push('shlimy')
      console.log(person1.friends)// ["shelly", "Bob", "shlimy"]
      ==引用类型值会共享值类型不会共享,因为在改变值类型时,相当于给自己添加了属性==
      ==当去修改引用类型的某个值时,是在修改__proto__中的对象。但如果直接给引用类型赋值,那也和值类型一样,是给自己增加了属性==
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 寄生式继承
     var person={
        name:'ccdida',
        friends:['shelly','Bob']
      }
      function createAnother(original){
        //clone.__proto__===original
        var clone=Object.create(original)
        //增强对象,添加属于自己的方法
        clone.sayHi=function(){
          console.log('hi')
        }
    
        return clone
    
      }
      var person1=createAnother(person)
      var person2=createAnother(person)
      person1.friends.push('shmily')
      console.log(person2.friends)//["shelly", "Bob","shmily"]
      person1.sayHi() //hi
      ==不能做到函数复用,引用类型数据依然共享==
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 寄生组合式继承
    通过借用构造函数来继承属性(apply),通过原型链的混成形式来继承方法(Object.create)
    
    前面的组合继承有个缺点:每次创建实例时都会调用两次超类方法,一次是通过new设置原型的时候,另一次是用apply执行的时候
     // 寄生组合继承:这个过程既实现了继承,又没有去调用Super
      function inheritPrototype(Sub,Super){
        //subPrototype.__proto__=Super.prototype
        var subPrototype=Object.create(Super.prototype)
        //subPrototype.constructor=Sub
        subPrototype.constructor=Sub
        //相当于subPrototype有__proto__和constructor两个属性
        //即:
        //Sub.prototype.__proto__===Super.prototype
        //Sub.prototype.constructor=Sub
        Sub.prototype=subPrototype
        
      }
      function Super(name){
        this.name=name
      }
      Super.prototype.sayHi=function(){
        console.log(this.name)//ccdida
      }
      function Sub(name){
        Super.call(this,name)
      }
      inheritPrototype(Sub,Super)
    
      Sub.prototype.sayHello=function(){
        console.log('sayHello')
      }
    
      var instance1=new Sub('ccdida')
      // instance1.sayHi()
      console.log(instance1.__proto__)
      console.log(instance1.__proto__.__proto__)
      
    ==实例通过Super.call(this,name)拿到Super中的属性(这些属性属于实例本身,不会被共享)==
    
    ==子类通过Object.create,让子类的原型对象的隐式原型(proto)指向父类的原型对象,完成方法的继承(可复用)==
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

  • 相关阅读:
    从SPL看开放计算能力的意义
    计算机毕业设计Java华夏球迷俱乐部网站设计与实现(源码+系统+mysql数据库+lw文档)
    抗量子计算简述
    七、MySql表的内置函数
    [HFCTF2020]BabyUpload session解析引擎
    每日一库:Prometheus
    山东企业ITSS认证条件
    关于计算机找不到d3dx9_43.dll,无法继续执行代码修复方法
    安卓中在使用poi来操作excel导入的时候异常信息
    java获取近期视频流关键帧与截图
  • 原文地址:https://blog.csdn.net/regretTAT/article/details/133764455