1.跨域
跨域原因 => 浏览器的同源策略 属于一种保护机制
如果没有同源策略的保护
一般用来处理登录cookie、服务端验证通过后会在响应头加入Set-Cookie字段、下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中、也就是说跳转到其他网站你也是携带Cookie过去的、就相当于你的账号被别人登录了、对方还能使用iframe获取dom节点进而获取你的账号密码
我们如何解决跨域
- 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<any>}*/
const request = ({url, data}) => {return new Promise((resolve, reject) => {// 处理传参成xx=yy&aa=bb的形式const handleData = (data) => {const keys = Object.keys(data)const keysLen = keys.lengthreturn 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.jsonpCbresolve(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)
})
- 空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中执行formform.target = iframe.nameform.method = 'post'for (let name in data) {node.name = namenode.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)。
只要同时满足以下两大条件,就属于简单请求。
参考文章地址
4.代理
Nginx conf配置
server{# 监听9099端口listen 9099;# 域名是localhostserver_name localhost;#凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 location ^~ /api {proxy_pass http://localhost:9871;}
}
参考链接地址
2. 继承
- 继承首先想到的是原型链继承
//例// 原型链继承function Super(){this.color=['red','yellow','black']}function Sub(){}//继承了color属性 Sub.prototype.color=['red','yellow','black']Sub.prototype=new Super()//创建实例 instance1.__proto__.colorconst 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传递值==
- 构造函数继承
function Super(name,age){this.name=namethis.age=agethis.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()==方法只能定义在构造函数中,函数无法复用==
- 组合继承
function Super(name,age){this.name=namethis.age=agethis.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,指向SuperSub.prototype=new Super()//constructor重新指向SubSub.prototype.constructor=Subconsole.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等),不会相互影响、通过原型链继承了父类的方法,实现了函数复用==
- 原型式继承
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__中的对象。但如果直接给引用类型赋值,那也和值类型一样,是给自己增加了属性==
- 寄生式继承
var person={name:'ccdida',friends:['shelly','Bob']}function createAnother(original){//clone.__proto__===originalvar 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==不能做到函数复用,引用类型数据依然共享==
- 寄生组合式继承
通过借用构造函数来继承属性(apply),通过原型链的混成形式来继承方法(Object.create)前面的组合继承有个缺点:每次创建实例时都会调用两次超类方法,一次是通过new设置原型的时候,另一次是用apply执行的时候// 寄生组合继承:这个过程既实现了继承,又没有去调用Superfunction inheritPrototype(Sub,Super){//subPrototype.__proto__=Super.prototypevar subPrototype=Object.create(Super.prototype)//subPrototype.constructor=SubsubPrototype.constructor=Sub//相当于subPrototype有__proto__和constructor两个属性//即://Sub.prototype.__proto__===Super.prototype//Sub.prototype.constructor=SubSub.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)指向父类的原型对象,完成方法的继承(可复用)==