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.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)
})
- 空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)。
只要同时满足以下两大条件,就属于简单请求。
参考文章地址
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. 继承
- 继承首先想到的是原型链继承
//例
// 原型链继承
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传递值==
- 构造函数继承
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()
==方法只能定义在构造函数中,函数无法复用==
- 组合继承
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等),不会相互影响、通过原型链继承了父类的方法,实现了函数复用==
- 原型式继承
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__===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
==不能做到函数复用,引用类型数据依然共享==
- 寄生组合式继承
通过借用构造函数来继承属性(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)指向父类的原型对象,完成方法的继承(可复用)==