javacript

274 阅读20分钟

javascript运行机制:只要主线程空了,就会读取任务队列

属于单线程,但是有同步任务和异步任务
同步任务:在主线程排队执行任务,只有当一个任务执行完毕,才执行下一个任务
异步任务:不见入主线程,而进入任务队列,只有任务队列通知主线程,某个异步任务可以执行了,任务队列才进入主线程

console.log("1");
while(true){};
console.log("2")
// 结果打印 1
// 这是同步任务 , while 进入死循环 ,所以导致先忙不能执行
console.log("1");
setTimeout(function(){
    console.log("2")
},0);
while(true){};
// 结果打印 1
// 这是异步任务,当执行第二个时,进入队列,但是执行第三个是死循环,所以导致setTimeout不能执行
异步执行的运行机制

1.所有同步都在主线程上执行,形成一个执行栈
2.主线程上也有一个任务队列,只要异步有了结果,就在任务队列放置一个事件
3.一旦执行栈所有同步执行完毕,系统就会读取任务队列,看看有哪些事件,哪些对应的异步任务,于是结束等待,进入执行栈,开始执行。
4.主线程不断执行这三步

有四种情况会放入异步队列

1.setTimeout 和 setInterval
2.DOM事件
3.es6 Promise
4.ajax

javascript 的运行分两个阶段

1.预解析,把所有的函数定义提前,所有的变量提前声明,变量赋值不提前
2.从上到下执行

for(var i=0;i<5;i++){
    setTimeout(function(){
        console.log(i) // 5 5 5 5 5
    },0)
}
// 写后感:setTimeout会进入异步任务队列,所以当for循环执行完毕得到(5)才执行setTimeout结果是5个5

参考地址:https://baijiahao.baidu.com/s?id=1615713540466951098&wfr=spider&for=pc

javascript 声明提前

console.log(scope);  // 得到undefined
var scope
scope = 100;
console.log(scope) // 100
// 写后感:会将var声明的变量和function声明的函数预读到当前作用域的顶部,所以var是全局可以访问,导致变量声明提前
得到undefined

function add(){
    console.log(111111);
}
add();
function add(){
    console.log(3333333);
}
add();
// 后一个add覆盖前一个add,所以得到永远是第一个

javascript 由什么组成:ECMAScript / DOM / BOM

javascript 引入

1.在html引入
2.通过script脚本引入
3.(script defer):延迟加载,元素解析后完成
4.(script async):异步加载,但执行时会阻塞元素渲染

javascript 原始类型:

string number boolean null  undefined    object 
'11',   11,    true , null, undefined,   let obj = {}

基本类型:名和值存储在栈内存中

string ,number,boolean,null,undefined,symbol,BigInt
'11',   11,   true ,null undefined,

引用类型:名存储在栈内存中,值存储在堆内存中,栈内存有个地址指向堆内存的值

Object,function

javascript undefined null的区别

一、undefined:

1.声明变量,没有赋值

var a 
cosole.log(a)&emsp;// undefined

2.函数参数,在调用时,没有带参 

function add (id){
    console.log(id)// undefined
}
add() // 调用没有带参

3.对象没有赋值的属性

let o  = {}
console.log(o.p) // undefined
let a = new Object();
console.log(a.x) // undefined

4.函数没有返回值时

function too(x=11){
    console.log(x)
}
let x = too();
console.log(x) // undefined

//以下是 一个有返回值的demo
function foo(x=11){
    return x
}
let y = foo();
console.log(y) // 11
null:表示被定义了,但是这个值为空

javascript 隐式转换:false : 0 , true :1 , " " : 0

let t = true
if(t==1){
    alert("我是true但是我转换成1") // 我是true但是我转换成1
}
let t = false
if(t==0){
    alert("我是false但是我转换成0") // 我是false但是我转换成0
}
// 字符串
let b = ""
if(b==0){
    alert("我是空但是我转换成0") // 我是空但是我转换成0
}
// 对象和布尔比较
let t = [];
if(t==false){
    // 对象转换成空字符串 ,然后再转成数字0 ,false 转换成0再做比较
    alert("我是一个对象,但是我先转换为空(' ')在转换成数字")
    // 我是一个对象,但是我先转换为空(' ')在转换成数字
}
// 对象和字符串比较
let t = [1,2,3]
if(t=="1,2,3"){
    alert("对象和字符串比较,先把对象转换成字符串'1,2,3' ,然后再做比较")
}
// 对象和数字比较
let t = [1];
if(t==1){
    alert("我是先转成'1'再比较")
    // 字符串和数字比较
}
'1' == 1 // true
// 字符串布尔
'1' == true // true
'0' == false // true
// 特殊比较
undefined == null // true
let t = 444;
let yy = {a:0,b:5};
console.log(t+yy)//  444[object Object]
// 题目:
console.log(1+'true') // 1true
console.log(1+true) // 2
console.log(1+undefined) // NaN
console.log(1+null) // 1

什么事编程面向对象:是一种设计思想,简称:OOP,把公共的事物抽象成属性和方法进行编程

原型链和作用域链有什么区别:

原型链:针对构造函数;例如:我们创建一个函数,这个函数通过__proto__ 或 prototype 绑定属性,然后通过new这个函数,那么这个被new 出来的新函数就会继承该函数的属性。
通过新函数访问,但是新函数没有这个属性,所以要通过链式向上查找,这就是原型链
作用:用来修改和查找属性
function Add () {}
Add.prototype.id = "1111"
let a = new Add()
console.log(a.id)  // "1111"
作用域链:是针对变量;分有全局和局部,如果局部没有就向全局查找
let a = "你这个老头坏滴狠";
function too(){
    console.log(a)  // "你这个老头坏滴狠";
}

javascript 多态继承:

同一个事物:发出不同的形态
继承:同一个事物,继承相同的形态,

javascript 闭包:

1.读取其他函数内部变量的函数
2.子函数调用父函数的变量,变量不会被释放

javascript 类

function Person(name) // 共用属性
    this.name = name;
    // 共用实例
    this.userName = function(){
        console.log(this.name+'是我的爱人');
    }
    this.totalNum = function(){
        console.log("我共用")
    }
}
Person.prototype.Add = function(){
    console.log(this.name+"我添加了");
}
let b = new Person("LING");

b.userName();
b.Add();
// 想要继承类通过prototype new一个新的类
function ClassNameTest(){}
// 例子
ClassNameTest.prototype = new Person();
const tt = new ClassNameTest();
tt.totalNum();
/**
 *  获得的思想
*  创建一个类,首字母要大写
*  可以把共同的可复用性的放在类里面
*  独立状态的可用portotype 点来继承
*  使用类可以用new 一个变量来使用
*
 *  子类继承父类可以用通过prototype来实现
*  也要new 一个新的类通过变量调用类的方法
*  缺点:无法继承多个类
*
 * **/

javascript 变量提升:

var a = "1";
function foo(){
    let a = "44"
    console.log(a) // 44
    return a
}
foo()

javascript let const var 的区别:

1.let 是一个块级作用域,在函数内定义,对外部无影响;

let a = "444";
function foo(){
    let a = "我是谔谔"
    console.log(a)//  "我是谔谔"
}
console.log(a)//  "444"

2.const 是一个常量,定义后不能修改
3.var 是一个全局,可以修改,不初始化会得到undefined

javascript proto protoType的关系:

   function Person (){}
   let person = new Person();
   console.log(person.__proto__ == Person.prototype); // true
   console.log(Person.prototype.constructor==Person); // true

javascript 手写实现一个xhr:

// 创建一个xhr对象
var xhr = new XMLHttpRequest()
xhr.open ("get","文件名地址","布尔,false表示同步请求,true表示异步请求")
xhr.onreadystatechange = function(){
    // readystate 
    // 0 表示未初始化,xhr对象已调用,open方法没有执行
    // 1表示初始化,send方法没有执行
    // 2表示发送数据,http请求头未知
    // 3表示数据发送中,但是http请求头不全,导致responseBody和responseText报错
    // 4表示数据接收完毕,responseBody和responseText回应请求的数据
    console.log(xhr.readystate)
    if(xhr.readystate==4 && xhr.status==200){
    // 表示数据接收完毕 ,http状态200
    }
}
xhr.send()
post 请求
let xhr = new XMLHttpResquest();
xhr.open('post','aa.text?parmes=1&id=2');
xhr.onreadystatechange = function(){
    if(xhr.readystate==4 && xhr.status==200){
        alert("成功")
    }
}
xhr.setRequsetHeader ('Content-Type','applicaiton/x-www-form-urlencoded');
xhr.send("?parmes=1&id=2");
使用promise 封装ajax
let fetch = (method,url)=>{
    rerurn new Promise((reject,resolve)=>{
        let xhr = new XMLHttpRequest();
        xhr.open(method,url);
        xhr.responseType = "json";
        xhr.setRequsetHeader ("Accept","application/json");
        xhr.readystatechange = function(){
            if(xhr.readystate==4 && xhr.status==200){
                resolve(this.response)
            }else{
                reject(this.response)
            }
        }
        xhr.send();
    })
}
fetch('get','https://www.baidu.com').then(({code,msg,res})=>{
    console.log(code,msg,res)
}).catch(()=>{});

https:

  get和post请求的区别
  get和post都没有长度限制,长度限制是web浏览器的url限制
  get可以是获取用户数据,所以不用每次和数据库连接,
  post 是用户操作交互,删除和修改,所以每次都需要请插入和删除数据库

http请求状态码:

2.101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议

3.200 OK 一切正常,对GET和POST请求的应答文档跟在后面。

4.302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。

5.303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取

6.304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。

7.305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取

8.307 Temporary Redirect 和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时才能重定向。由于这个原因,HTTP 1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。

9.400 Bad Request 请求出现语法错误。

10.401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。

11.403 Forbidden 资源不可用。

12.404 Not Found 无法找到指定位置的资源

13.405 Method Not Allowed 请求方法(GET、POST、HEAD、Delete、PUT、TRACE等)对指定的资源不适用。

14.500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求 、

15.501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求

16.502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答

17.503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头

18.504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答

19.505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本

javascript section cookies localStorage sessionStorage:

/*
* 保存状态:cookie 存在浏览器端,session 存在服务端,
*
* 1、使用方式:
* cookie 分两种:
* 1.如果没有设置过时间,随着浏览器的关闭而消失
* 2.如果设置过期时间,过期时间到,cookie会自动消失
* cookie 是以文本方式保存在客户端,每次请求都带上它
*
* session 有没有sessionId 有这个返回一个session对象,没有这个创建一个新的session对象
* 分三种情况:禁用cookie则重写response.encodeURL(url)
*           不支持cookie 将会重写url把sessionId拼接搭到url后面
*           支持则url不做任何处理
*
*
* 2、存储内容:
* cookie 以文本格式存储, session 类似hashtable数据格式存储,
可以存储多个对象(session)
*
* 3、存储的大小
* cookie 单个不能超过4kb, session 没有大小限制
*
*4、 安全性
* cookie 容易被拦截,欺骗, session 的sessionId是保存在cookie里的,所以安全大于cookie
*
* 应用场景:
* cookie 用户登陆过,下次可以记住用户信息,方便登陆;
保存上次的登录时间;
保存上次查看的页面;统计查看次数
*
*缺点:
*   cookie 大小限制,不安全
*   session 不利于用户量多使用,占服务器内存
*
*
*localStorage:存在本地,永久性存储,大小5mb,没有跟服务器接触
*
*sessionStorage:仅在当前会话,浏览器关闭就结束,大小5mb,没有跟服务器接触
*
*
* */

模块化

作用:提高了可扩展、可维护、可协作性
1.ES6 :import / 对应的是 exports
2.common.js: require / export.module exports
3.amd:rquire / defined

import 和 require 的区别

import是异步,require是同步
import指向内存地址,所以导入值会随着导出值而改变
require是值拷贝,导出值变化不会改变导入值

javascript 重绘和回流,防抖,节流

重绘:不改变布局大小,只改变样式和文本
回流:改变页面布局,重新计算文档元素
防抖:多次触发事件,事件之执行一次,并且是在事件结束后执行
应用场景:比如按钮,多次点击,将多次操作合并成一次操作
节流:在规定时间内,只执行一次,一定时间内只触发一次
应用场景:滚动条,缩放页面

// 防抖
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #container {
            width: 100%;
            height: 80px;
            line-height: 80px;
            background-color: black;
            color: #fff;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="container"></div>
<script>
    const container = document.getElementById("container");
    let count = 1;
    function add(e){
        console.log(e,"getHtml")
        container.innerText = count++;
    }
    function getHtml(func,wait,isflag) {
        let time,result;
        return function () {
            time && clearTimeout(time);
            let context = this;
            let arg = arguments;
            if(isflag){
                let callnow = !time;
                time = setTimeout(()=>{
                    time = null
                },wait);
                if(callnow) result=func.apply(context,arg)
            }else {
                time = setTimeout(()=> {
                    func(context, arg)
                }, wait)
            }
            return result;
        }
    }
    container.onclick = getHtml(add,300);

</script>
</body>
</html>
// 节流
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节流</title>
    <style>
        #content{
            width:20px;
            height: 20px;
            background-color: black;
            overflow: auto;
        }
    </style>
</head>
<body>
<div id="content">留图不留种,菊花万人捅;留种不留图,菊花万人服</div>
<script>
    let content = document.getElementById('content');
    let falg = true;
    content.onscroll = function () {
        if(!falg) return;
        falg = false;
        setTimeout(function () {
            console.log("函数节流");
            falg = true
        },300)
    }
</script>
</body>
</html>

javascript DOM有哪些api

nodeType:

html:<div id="container"></div>

let container = document.getEleMentById('container');
container.nodeType // 判断是什么元素 
/**
1.表示标签元素
2.表示元素属性
3.表示文本
8.表示注释
9.表示文档 (document)
11.表示轻量级文档 (DocumentFragment)
nodeValue:获取内容

创建api:
createElement 创建标签元素
createTextNode 创建文本
cloneNode 复制一个节点副本
**/
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="content">
    <span>我可以复制哦</span>
</div>
<button id="btn">复制</button>
<script>
    let content = document.getElementById('content');
    let btn = document.getElementById("btn");
    btn.onclick = function () {
        let content1 = content.cloneNode(true);
        content1.id="content1";
        document.body.appendChild(content1);
    }
    /**
     * 获取id
     * 通过点击事件触发
     * id.cloneNode(true) // 复制节点副本
     * 添加id
     * 使用appendChild 插入到body
     *
     *
     * **/
</script>
</body>
</html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul id="list"></ul>
<input type="button" value="点我" onclick="handleClick()"/>
<input type="button" value="爱我" onclick="handleBtn()"/>
<script>
    let listID = document.getElementById("list");
    // function handleBtn(){
    //     console.time("antzone");
    //     for (let i =0;i<10;i++){
    //         let lis = document.createElement('li');
    //         lis.textContent = i;
    //         listID.appendChild(lis);
    //
    //     }
    //     console.timeEnd("antzone"); 
    //
    // }
    let Fragment = document.createDocumentFragment();
    function handleClick() {
        console.time("antzone");
        for(let i =0;i<10;i++){
            let list = document.createElement('li');
            list.textContent = i;
            // 先放进片段
            Fragment.appendChild(list)
        }
        // 后面一次性再加入片段
        listID.appendChild(Fragment);
        console.timeEnd("antzone"); //antzone: 
    }
    /**
     * 获取id
     * 通过点击事件处理
     * 使用createElement创建元素
     * textContent 文本内容
     * 性功能要求:
     * 第一个方案:每次都会创建一个新的元素,然后添加到文档树中,造成浏览器回流
     * 第二个方案:每次先添加到Fragment,然后再一次性添加到ul中
     *
     *
     * **/
</script>
</body>
</html>
// appendChild 在后插入
// inserBefor 在前面插入
// removeChild 删除
// replaceChild 替换一个元素
查找api:

  getElementById() // 查找id
  getElementsClassName() // 查找class
  getElementsByTagName() // 查找标签元素
  querySelectorAll() // 通过class 查找所有
  querySelector() // 查找一个

修改属性:
setAttribute ('name',value) // 修改属性
getAttribute('name') // 获取属性

javascript mvc mvvm mvp的区别

mvc:module-view-controller

用户操作(view)=>业务逻辑处理(controller)=>数据持久化(module)=>用户视图(view)

mvp:module-view-Presenter

用户视图(view)=>Presenter=>数据持久化(module)

mvvm:module-view-viewModule

用户视图(view)<=>viewModule<=module(数据持久化)

好处:可实现数据绑定

参考地址:https://www.cnblogs.com/guwei4037/p/5591183.html

javascript 浅拷贝和深拷贝

浅拷贝:
基本类型:名和值存储在栈内存中  
引用类型:名存储在栈内存,值存在堆存中,栈内存提供一个引用地址指向堆内存,      

a = b

a改变b也跟着改变,其实就是引用地址一样

let a = [1,2,3,4,5,6]; 
b = a; 
//a [1, 2, 3, 4, 5, 6] 
//b [1, 2, 3, 4, 5, 6] 
a[0] = 1; 
//a  [1, 2, 3, 4, 5, 6] 
//b  [1, 2, 3, 4, 5, 6]
a[0] = "11"; 
// a ["11", 2, 3, 4, 5, 6] 
// b ["11", 2, 3, 4, 5, 6]
深拷贝:

a = b

但是a不受b影响

let aa ={a:'1',b:'2'}; 
let bb = {}; 
let dd = Object.assign(bb,aa); 
//dd {a: "1", b: "2"} bb {a: "1", b: "2"} 
//aa {a: "1", b: "2"} 
aa.name="333" 
// aa {a: "1", b: "2", name: "333"} 
// aa修改了,但是bb和dd没有修改 
// bb {a: "1", b: "2"} 
// dd {a: "1", b: "2"}

javascript alert的调用

    alert([1,2,3,[4,5,6]]); //输出的结果是1,2,3,4,5,6
    alert([1,2,3]); //输出的结果是1,2,3

javascript 跨域问题

什么是跨越:不同协议,域名,端口的访问

(不是跨域)

www.aaa.com/index.html 调用 www.aaa.com/home.php

(跨域,域名不同)

www.aaa.com/index.html 调用 www.bbb.com/index.html

(跨域,协议不同)

www.aaa.com/index.html 调用 http:// www.aaa.com/index.html

(跨域,端口不同)

www.aaa.com:8080/index.html

调用

www.aaa.com:9090/index.html

为什么浏览器要限制跨域:当用用户访问一个页面时,用户的信息会存储在浏览器端,如果用户访问其他网站,就会泄露该用户信息

为什么要跨域:有安全问题,也有的公司有很多不同域名,所以要访问公共资源就要用到跨域

解决跨域的方法:

1、CORS资源共享:只需要在后台中加上响应头来允许域请求!在被请求的Response header中加入以下设置,就可以实现跨域访问了!

 //指定允许其他域名访问
'Access-Control-Allow-Origin:*'//或指定域
//响应类型
'Access-Control-Allow-Methods:GET,POST'
//响应头设置 'Access-Control-Allow-Headers:x-requested-with,content-type'    

2、jsonp:就是用javascript脚本回调一个方法,获取到相应的数据

<script src="https://www.aaa.com/index.html?callback=jsonpFunc"></script>
<scirpt>
    function jsonpFunc(jsonpData){
        console.log("获取到的数据:",jsonpData)
    }
</script>    

3、 通过修改documment.domain

a.html

<iframe 
    src="https://www.baidu.com/b.html" 
    id="iframe" 
    onload="test()" 
    frameborder="0" 
/>
document.domain = "hdq.com"// 设置主域名
function test() {
    console.log(document.getElementById('iframe').contentWindow);
}

b.html

document.domain = "hdq.com"// 设置主域名

4、使用window.name来进行跨域

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口 载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

5、使用html5 window.postMessage跨域

a.html

// 打开a.html会打印{a:'333',b:'bbb',c:'444'};
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<iframe src="./b.html" frameborder="0" id="iframe" onload="test()"></iframe>
<script>
    let obj = {a:'333',b:'bbb',c:'444'};
    function test() {
        let iframe = document.getElementById('iframe');
        let win = iframe.contentWindow;
        win.postMessage(obj,'*')  
    }
</script>
</body>
</html>

b.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    window.onmessage = function (e) {
        let event =  e || event ;
        console.log(event.data)
    }
</script>
</body>
</html>

6、使用web sockets

什么是web sockets:浏览器提供的一种api,它的目标是给一个单独持久的链接上提供双工、双向通信

sockets原理:js创建sockets后,会有一个http请求发送到浏览器已发起链接,取得响应后,由http升级http协议转换成web sockets协议

let socket = new WebSockt('ws://www.aaa.com');//http->ws; https->wss
socket.send('你好我是web sockets');
socket.onmessage = function(event){
    let data = event.data;
}

7、nginx反向代理解决跨域

修改nginx.conf

server
    {
        #监听端口
        listen 80; 

        #服务访问域名
        server_name localhost; 

        location /api/ { 
            # 反向代理的地址
            proxy_pass http://localhost:8888/; 

            # 对发送给客户端的URL进行修改
            proxy_redirect off; 
             
            # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   

            # 允许客户端请求的最大单文件字节数
            client_max_body_size 10m;  
 
            # 缓冲区代理缓冲用户端请求的最大字节数      
            client_body_buffer_size 128k;

            # 表示使nginx阻止HTTP应答代码为400或者更高的应答。
            proxy_intercept_errors on;

            # nginx跟后端服务器连接超时时间
            proxy_connect_timeout 90;

            # 后端服务器数据回传超时时间
            proxy_send_timeout 90;

            # 连接成功后,后端服务器响应超时时间
            proxy_read_timeout 90;

            # 设置代理服务器(nginx)保存用户头信息的缓冲区大小
            proxy_buffer_size 4k;
           
            # 设置用于读取应答(来自被代理服务器)的缓冲区数目和大小
            # 默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
            proxy_buffers 4 32k;

            # 高负荷下缓冲大小(proxy_buffers*2)
            proxy_busy_buffers_size 64k;

            # 设置在写入proxy_temp_path时数据的大小,
            #预防一个工作进程在传递文件时阻塞太长
            proxy_temp_file_write_size 64k;
        }       
        
    }
}

//常见配置
location /api/ {  
    proxy_pass http://localhost:8888/;
    proxy_pass_request_headers on;
    proxy_set_header Connection "";       
    client_max_body_size    30m;
    client_body_buffer_size 128k; 
    proxy_redirect off;
    proxy_connect_timeout   300;
    proxy_send_timeout      300;
    proxy_read_timeout      300;
    proxy_buffer_size       4k;
    proxy_buffers           4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
    proxy_next_upstream http_502 http_504 error invalid_header; 
}

server {
        listen       80; #监听80端口,可以改成其他端口
        server_name  localhost; # 当前服务的域名

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://localhost:81;
            proxy_redirect default;
        }

		location /apis { #添加访问目录为/apis的代理配置
			rewrite  ^/apis/(.*)$ /$1 break;
			proxy_pass   http://localhost:82;
       }
#以下配置省略
// 使用
<h2>Index</h2>
<div id="show"></div>

<script type="text/javascript">
        $(function () {
            $.get("/apis/api/values", {}, function (result) {
                $("#show").html(result);
            })
        })
</script>

8、proxyTable解决跨域

proxyTable: {
    '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: {
            '^/api': ''
        }
    }
}
axios.get('/api/list').then((res)=>{
    console.log('success')
}).catch((res)=>{
    console.log('error')
})

javascript 当在浏览器输入url发生了什么

  1、解析url
  2、DNS解析(实际上是域名和ip对应的数据库)
  3、浏览器与tcp建立三次握手
  4、请求和传输数据
  5、页面渲染

javascript tcp三次握手

  1、客户端向服务器发送请求
  2、服务器端接收到请求,返回一个指令
  3、客户端接收到服务端回复指令并返回确认   

浏览器渲染页面:

  1、解析html,创建dom树
  2、解析css,创建style Rule 
  3、合并dom树和style Rule,计算每个节点样式
  4、绘制完成显示在屏幕上

渲染优化:

1.HTML文档结构层次尽量少,最好不深于六层;

2.脚本尽量后放,放在前即可;

3.少量首屏样式内联放在标签内;

4.样式结构层次尽量简单;

5.在脚本中尽量减少DOM操作,尽量缓存访问DOM的样式信息,避免过度触发回流;

6.减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;

7.动画尽量使用在绝对定位或固定定位的元素上;

8.隐藏在屏幕外,或在页面滚动时,尽量停止动画;

9.尽量缓存DOM查找,查找器尽量简洁;

10.涉及多域名的网站,可以开启域名预解析

javascript 数组和对象的方法

数组:

forEach,map,fillter,find,join,shift,unshift,push,concat,replase,sort,slice,reduer,indexOf,some,reverse(数组反转[1,2,3] =>[3,2,1])

对象:

let a = new Object();

javascript splice和concat

array.splice(start,deteleCount,item,item1)
start 相当于length,
deteleCount 删除多少位
splice 实现删除,替换,插入

let b = ['a','1','b','2','c','3','d','4']
b.splice(1,2) // ["1", "b"]
b  // ["a", "2", "c", "3", "d", "4"]
b.splice(4,2) // ["d", "4"]

slice

let c = [1,2,3,4,5,6];
c.slice(4)  // [5, 6]
c // 没有改变  [1,2,3,4,5,6]
concat 将参数添加到数组

react 高阶组件

属性代理:高阶组件通过被包裹的React组件来操作props

反向继承:高阶组件继承于包裹的React组件

属性代理:

import React,{Component} from "react"

const MyContainer = (wrappedComponent)=>
    class extends Component {
        render(){
            return(
                <wrappedComponent {...this.props}/>
            )
        }
    }


class MyContent extends Component{
    render(){
        return(
            <div>dddd</div>
        )
    }
}

export default MyContainer(MyContent);


// 相等于

// 使用decorator转换
@MyContainer

class myContent extends Component{
    render(){}
}

export default myContent;

手册题

[1,2,3].map(parseInt) // [1,'NaN','NaN']
parseInt([1,2,3]) // 1
parseInt('1', 0); // 1 (parseInt的处理方式,这个地方item没有以"0x"或者"0X"开始,
8和10这个基数由实现环境来定,ES5规定使用10来作为基数,因此这个0相当于传递了10)
parseInt('2', 1); // NaN (因为parseInt的定义,超出了radix的界限)
parseInt('3', 2); // NaN (虽然没有超出界限,但是二进制里面没有3,因此返回NaN)
// 程序中会有几种值转换false
console.log(Boolean(undefined)) // false
console.log(Boolean("")) // false
console.log(Boolean(0)) // false
console.log(Boolean(null)) // false
console.log(Boolean(-0)) // false
console.log(Boolean(NaN)) // false
async function async1() {
    console.log("a");
    await async2();
    console.log("b");
}
async function async2() {
    console.log('c')
}

console.log("d");

setTimeout(function () {
    console.log("e");
},0)

async1();

new Promise(function (resolve) {
    console.log("f");
    resolve();
}).then(function () {
    console.log("g");
})

console.log("h");
// 输出的结果是 d=>a=>c=>f=>h=>b=>g=>e
for (var i=0;i<5;i++){
    console.log(i); // 0, 1, 2, 3, 4,
    setTimeout(function () {
       console.log(i) // 5 5 5 5 5
    },0)
}

for (let i=0;i<5;i++){
    console.log(i); // 0, 1, 2, 3, 4
    setTimeout(function () {
        console.log(i);// 0, 1, 2, 3, 4
    },0)
}
function fn(){
    for(var i =0;i<5;i++){
        setTimeout(()=>{
            console.log(i) // 5
        },2000)
    }
}
fn() // 
function fn(){
    for(let i =0;i<5;i++){
        setTimeout(()=>{
            console.log(i) // 0,1,2,3,4
        },2000)
    }
}
fn() //