layout 笔记

  • 观察者模式 基于 发布订阅模式
  • promise 用于解决异步方案 promise函数中的executor函数会立即执行
  • promise三大状态:
    • pending 等待状态
    • resolved(fulfilled) 成功状态
    • rejected 失败状态
  • generator async+awite 支持try{}catch(e){}
  • co库源码
function co(it){
     return new promise(()=>{
        function next(val){
            let {value,done} = it.next(val);
            if(done){
                return  resolve(value)
             }
            Promise.resolve(value).then(data=>{
              next(data)
             })
          }
     })
  }
  • var let const 区别:
    • var 变量提升 全局
    • let 解决重复定义 拥有自己的作用域
    • const 常亮 不会变的量(地址不变即可)
  • 展开运算符(...)
let  a = [1,2,3];
let  b =[4,5,6];
let c = [...a,...b]
  • 深拷贝
function deepCopy(options,hash=new WeakMap()){
    if(options == null) return options;
    if(options instanceof Date) return new Date(options);
    if(options instanceof RegExp) return new Date(options);
    if(typeof options !== 'object') return options;
    //如果 weakmap中有对象 就直接返回
    if(hash.has(options))return hash.get(options);
    let cloneOptions = new options.constructor;
    hash.set(obj,cloneOptions );
    for(let key in options){
         if (obj.hasOwnProperty(key)) {
              //如果赋值的对象 就把这个对象放到weakmap中
              cloneOptions[key] = deepCopy(obj[key],hash)
        }
    }
    return cloneOptions 
}
  • object.defineProperty()属性 不支持数组更新(push sclice...)

    • enumerable : true/false 是否可枚举
    • configurable : true/false 是否可删除
    • writable : true/false 是否可重新
    • get(){} //不能和writable 同时存在
    • set(){} //不能和writable 同时存在
  • object.proxy()

     let proxy = new Proxy(arr,{
         set(target,key,value){
               if( key === 'length'){
                  return true
                }
               //不能操作原数组
               return Reflect.set(target,key,value)
              // target[key] = value
         },
         get(target,key){
                return Reflect.get(target,key)
               //return target[key]
         }
    })
    
    
  • reduce原理

  Array.prototype.my_reduce = function(cb, prev) {
    for (let i = 0; i < this.length; i++) {
        if (typeof prev !== 'undefined') {
            prev = cb(prev, this[i], this)
        } else {
            prev = cb(this[i], this[++i], this);
            i++;
        }
    }
    return prev
  };
  • some() 找到对应值就返回true

  • every() 找到对应值就返回false

  • 原型

    • 每个实例上的proto 都指向所属类的原型(prototype)
  • object.create()原理

function create(parentPrototype){
  let Fn = function(){}
  Fn.prototype = parentPrototype;
  let fn = new Fn();
  return fn
}
  • 装饰器
    • 需安装
    1. @babel/plugin-proposal-decorators
    2. @babel/plugin-proposal-class-properties
  • *注 插件有顺序
@flag
class Animal{
    //实例属性
    @readonly
    PI = 3.14;
    //静态属性(自己拥有)
    static name = 'sss';
    //原型上
    say(){}
}
function flag(_class){}
function readonly(target,property,descriptor){}
  • node事件环

    • 栈 先进后出
    • 队列 先进先出
  • node

    • 解决跨域问题
    • 高并发高性能服务器
    • 适合I/O密集型(fs)
    • 不适合cpu密集型(加密 运算)
  • node 事件环

    • timers阶段 setTimeout
    • poll(轮询) 阶段 I/O
    • check阶段 setImmediate
  • path 模块

   path.extname  //获取文件扩展名
   path.basename //文件名(无后缀)
   path.join() //路径拼接
   path.resolve() //把文件路径转换成绝对路径
   path.dirname() // 获取父级目录
   __dirname   //目录名 文件名
   __filename  //文件名
  • 字符串执行方法
  1.eval()
  2. new Function(argument,str)
  3. vm (沙箱 node核心模块) 
  • npm link 把包链接到全局上
  • 文件运行方式 #!/usr/bin/env node
  • chmod -R 777 路径 修改目录权限
 pack.json文件中:
     bin :{
       "命令名":"运行文件"
     }
process.cwd() //当前执行文件路径
  • 宏任务/微任务

    • 微任务:process.nextTick promise MutationObserver
    • 微任务: script setTimeout setInterval MessgeChannel I/O UI rendering
  • node 包 utils EventEmitter buffer

  • fs access() 判断是否有权限访问该路径(是否存在)

function next(index){
    fs.access(path,(err)=>{
        if(err){
            fs.mkdir(currentpath,()=>next(index+1))
        }else{
            next(index)
        }
    })
}
  1. 删除目录 rmdirSync(dir)
  2. 删除文件 unlinkSync(dir)
  3. 文件状态 statSync(dir)
  4. 读取目录readdirSync(dir)
  5. 判断是文件夹还是文件 isDirectory()
let rs = fs.createReadStream(path,{
            flags:'r',//r, r+, w, w+, a,
            highWaterMark:1,//字节数
            mode:0o666, //可读可写
            start:0,//开始位置
            end:3,//结束位置
            //encoding:'utf8'
            autoClose:true
        })
rs.on("open", ()=>{})   //打开文件
rs.on("close",()=>{})   //关闭文件
rs.on("error",()=>{})   //读取文件出错
rs.on("data", (chunk)=>{})   //读取文件
rs.on("end",  ()=>{})   //读取完毕
rs.resume()   //恢复
res.pause()   //暂停
  • readStream 源码:
let fs = require('fs');
let EventEmitter = require('events')
class ReadStream extends EventEmitter {
    constructor(path, options = {}) {
        super();
        this.path = path;
        this.flags = options.flags || 'r';
        this.mode = options.mode || 438;
        this.start = options.start || 0;
        this.end = open.end;
        this.autoClose = options.autoClose;
        this.highWaterMark = options.highWaterMark || 64 * 1024;
        this.encoding = options.encoding || null;
        this.flowing = null; //开始读取 修改成true
        // 读取文件 需打开文件
        this.open();
        // 同步
        this.on("newListener", (type) => {
            if (type === 'data') {
                this.flowing = true;
                this.read() //开始读取文件
            }
        })
        this.pos = this.start;
    }
    read() {
            if (typeof this.fd !== 'number') {
                return this.once('open', () => this.read())
            }
            let howMuchToRead = this.end ? Math.min((this.end - this.pos + 1), this.highWaterMark) : this.highWaterMark;
            let buffer = Buffer.alloc(howMuchToRead);
            fs.read(this.fd, buffer, 0, buffer.length, this.pos, (err, bytesRead) => {
                if (bytesRead > 0) {
                    this.pos += bytesRead;
                    this.emit("data", this.encoding ? buffer.toString(this.encoding) : buffer);
                    if (this.flowing) {
                        this.read()
                    } else {
                        this.emit('end');
                        if (this.autoClose) {
                            fs.close(this.fd, () => {
                                this.emit("close");
                                this.flowing = null;
                            })
                        }
                    }
                }
            })
        }
        //异步
    open() {
        fs.open(this.path, this.flags, (err, fd) => {
            if (err) {
                this.emit('error');
                return
            }
            this.fd = fd; //文件描述符
            this.emit('open', this.fd)
        })
    }
}
module.exports = ReadStream;
  • writeStream 源码:
/**
 * 第一次 向文件中写入
 * 第二次 把内容存放到缓存中
 * 第三次 第一次写入成功后,清空缓存第一项 依次清空
 * 第四次 都清空后看是否触发drain事件
 */
let fs = require('fs');
let EventEmitter = require('events')
class WriteStream extends EventEmitter{
    constructor(path,options){
      super();
      this.path= path;
      this.mode = options.mode||0o666;
      this.autoClose = options.autoClose|| true;
      this.highWaterMark = options.highWaterMark || 64 * 1024;
      this.encoding = options.encoding || 'utf8';
      this.start = options.start || 0;
      this.flags = options.flags || 'w';
      this.open();
      this.cache=[];//暂存
      this.len;
      this.needDrain = false;
      this.writing = false;
      this.pos =this.start;
    }
    open(){
      fs.open(this.path,this.flags,(err,data)=>{
          if(err){
            return this.emit("error")
          }
          this.fd = fd;
          this.emit("open")
      })
    }
    write(chunk,encoding=this.encoding,callback=()=>{}){
      chunk =Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk);
      this.len += chunk.length;
      if(this.len >= this.highWaterMark){
        this.needDrain = true;
      }
      if(this.writing){
        this.cache.push({chunk,encoding,callback})
      }else{
        this.writing = true;
        this._write(chunk,encoding,()=>{
          callback();
          this.clearBuffer()//  清理数组第一项
        })
      }
      return  !this.needDrain;
    }
    clearBuffer(){
      let obj =  this.cache.shift();
      if(obj){
        this._write(obj.chunk,obj.encoding,()=>{
          obj.callback();
          this.clearBuffer();
        })
      }else{
        if(this.needDrain){
          this.needDrain =false;
          this.writing = false;
          this.emit("drain")
        }
      }
    }
    _write(chunk,encoding,callback){
      if(typeof this.fd != 'number'){
        return this.once("open",()=>{
          return this._write(chunk,encoding,callback)
        })
      }
      fs.write(this.fd,chunk,0,chunk.length,this.pos,(err,written)=>{
        this.pos = written;
        this.len -= written
        callback()
      })
    }
}
module.exports = WriteStream
  • process.stdout.write()可写流
  • process.stdin.on("data",(chunk)=>{}) 可读流
  • process.stdin.pipe()
  • HTTP 状态码:
    • 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码。
      • 100 (继续) 请求者应当继续提出请求。
      • 101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。
  • 2xx (成功) 表示成功处理了请求的状态代码。
    • 200 (成功) 服务器已成功处理了请求。
    • 201 (已创建) 请求成功并且服务器创建了新的资源。
    • 202 (已接受) 服务器已接受请求,但尚未处理。
    • 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
    • 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
    • 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
    • 206 (部分内容 断点续传(range:bytes=0-5)) 服务器成功处理了部分 GET 请求。
  • 3xx (重定向) 表示要完成请求,需要进一步操作。
    + 300 (多种选择) 针对请求,服务器可执行多种操作。
    + 301 (永久移动) 请求的网页已永久移动到新位置。
    + 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
    + 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
    + 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
    + 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
    + 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

  • 4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理。
    + 400 (错误请求) 服务器不理解请求的语法。
    + 401 (未授权) 请求要求身份验证。
    + 403 (禁止) 服务器拒绝请求。
    + 404 (未找到) 服务器找不到请求的网页。
    + 405 (方法禁用) 禁用请求中指定的方法。
    + 406 (不接受) 无法使用请求的内容特性响应请求的网页。
    + 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
    + 408 (请求超时) 服务器等候请求时发生超时。
    + 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
    + 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
    + 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
    + 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
    + 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
    + 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
    + 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
    + 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
    + 417 (未满足期望值) 服务器未满足”期望”请求标头字段的要求。

  • 5xx(服务器错误) 这些状态代码表示服务器在尝试处理请求时发生内部错误。
    + 500 (服务器内部错误) 服务器遇到错误,无法完成请求。
    + 501 (尚未实施) 服务器不具备完成请求的功能。
    + 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
    + 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
    + 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
    + 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

  • http头:

    • 设置语言
           Accept - language:zh-CN, jp;q=0.8
      
    • 断点续传
        Content-Rang:bytes 0-5/total
      
    • 防盗链(referer)
        let refererHost = url.parse(req.headers['referer']).host;
        let  host = req.headers['host']
        if(refererHost != host){
            不是同一网站
        }
      
    • 压缩
        zlib核心包 
        fs.createReadStream(path).pipe(zilb.createGzip()).pipe(res)
      
  • 高阶函数 (callback)解决异步问题 并发 基于回调(回调地狱 错误处理很复杂)

  • promise原理(必会 手写源码)

  • defer 实现defer的延迟对象(必会)

  • promise的优缺点:

    • 解决回调地狱 链式调用
  • co + generator (saga) yield *

  • async + await

  • es6

    • 箭头函数(没有this argument prototype) 原型链 各种继承
    • 解构 模板字符串 剩余运算符
    • 递归拷贝 + 解决循环应用 weakmap
    • Set,Map(去重 交差补) Symbol instanceof
    • Object.defineProperty -> proxy(解决数组问题 触发两次)+reflect 递归
    • class
  • eventloop事件环

    • 宏任务: settimeout messageCheenl setimmidate UI线程
    • 微任务:promise.then mutationobserver nexttick

你可能感兴趣的:(layout 笔记)