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>

/**
 * 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. 空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'
  }
})

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

只要同时满足以下两大条件,就属于简单请求。
Vue、js底层深入理解笔记(二)_第1张图片

参考文章地址

4.代理
Nginx conf配置

server{
    # 监听9099端口
    listen 9099;
    # 域名是localhost
    server_name localhost;
    #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
    location ^~ /api {
        proxy_pass http://localhost:9871;
    }    
}

参考链接地址


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. 构造函数继承
  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. 组合继承
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. 原型式继承
 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. 寄生式继承
 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. 寄生组合式继承
通过借用构造函数来继承属性(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)指向父类的原型对象,完成方法的继承(可复用)==


你可能感兴趣的:(JS,Vue底层深入理解笔记,javascript,vue.js,笔记)