美文网首页
layout 笔记

layout 笔记

作者: 嚎鹰_Y飞翔 | 来源:发表于2019-04-18 16:28 被阅读0次
    • 观察者模式 基于 发布订阅模式
    • 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 笔记

          本文链接:https://www.haomeiwen.com/subject/xbfnwqtx.html