layout 筆記

  • 觀察者模式 基于 發(fā)布訂閱模式
  • promise 用于解決異步方案 promise函數(shù)中的executor函數(shù)會立即執(zhí)行
  • promise三大狀態(tài):
    • pending 等待狀態(tài)
    • resolved(fulfilled) 成功狀態(tài)
    • rejected 失敗狀態(tài)
  • 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 區(qū)別:
    • 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()屬性 不支持數(shù)組更新(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
                }
               //不能操作原數(shù)組
               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;
    //靜態(tài)屬性(自己擁有)
    static name = 'sss';
    //原型上
    say(){}
}
function flag(_class){}
function readonly(target,property,descriptor){}
  • node事件環(huán)

    • 棧 先進后出
    • 隊列 先進先出
  • node

    • 解決跨域問題
    • 高并發(fā)高性能服務器
    • 適合I/O密集型(fs)
    • 不適合cpu密集型(加密 運算)
  • node 事件環(huán)

    • timers階段 setTimeout
    • poll(輪詢) 階段 I/O
    • check階段 setImmediate
  • path 模塊

   path.extname  //獲取文件擴展名
   path.basename //文件名(無后綴)
   path.join() //路徑拼接
   path.resolve() //把文件路徑轉換成絕對路徑
   path.dirname() // 獲取父級目錄
   __dirname   //目錄名 文件名
   __filename  //文件名
  • 字符串執(zhí)行方法
  1.eval()
  2. new Function(argument,str)
  3. vm (沙箱 node核心模塊) 
  • npm link 把包鏈接到全局上
  • 文件運行方式 #!/usr/bin/env node
  • chmod -R 777 路徑 修改目錄權限
 pack.json文件中:
     bin :{
       "命令名":"運行文件"
     }
process.cwd() //當前執(zhí)行文件路徑
  • 宏任務/微任務

    • 微任務: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. 文件狀態(tài) statSync(dir)
  4. 讀取目錄readdirSync(dir)
  5. 判斷是文件夾還是文件 isDirectory()
let rs = fs.createReadStream(path,{
            flags:'r',//r, r+, w, w+, a,
            highWaterMark:1,//字節(jié)數(shù)
            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 源碼:
/**
 * 第一次 向文件中寫入
 * 第二次 把內容存放到緩存中
 * 第三次 第一次寫入成功后锉走,清空緩存第一項 依次清空
 * 第四次 都清空后看是否觸發(fā)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()//  清理數(shù)組第一項
        })
      }
      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 狀態(tài)碼:
    • 1xx(臨時響應)表示臨時響應并需要請求者繼續(xù)執(zhí)行操作的狀態(tài)代碼涣易。
      • 100 (繼續(xù)) 請求者應當繼續(xù)提出請求。
      • 101 (切換協(xié)議) 請求者已要求服務器切換協(xié)議般眉,服務器已確認并準備切換。
  • 2xx (成功) 表示成功處理了請求的狀態(tài)代碼。
    • 200 (成功) 服務器已成功處理了請求。
    • 201 (已創(chuàng)建) 請求成功并且服務器創(chuàng)建了新的資源匆瓜。
    • 202 (已接受) 服務器已接受請求,但尚未處理未蝌。
    • 203 (非授權信息) 服務器已成功處理了請求驮吱,但返回的信息可能來自另一來源。
    • 204 (無內容) 服務器成功處理了請求萧吠,但沒有返回任何內容左冬。
    • 205 (重置內容) 服務器成功處理了請求,但沒有返回任何內容纸型。
    • 206 (部分內容 斷點續(xù)傳(range:bytes=0-5)) 服務器成功處理了部分 GET 請求拇砰。
  • 3xx (重定向) 表示要完成請求梅忌,需要進一步操作。
    + 300 (多種選擇) 針對請求除破,服務器可執(zhí)行多種操作牧氮。
    + 301 (永久移動) 請求的網(wǎng)頁已永久移動到新位置。
    + 302 (臨時移動) 服務器目前從不同位置的網(wǎng)頁響應請求瑰枫,但請求者應繼續(xù)使用原有位置來進行以后的請求踱葛。
    + 303 (查看其他位置) 請求者應當對不同的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼光坝。
    + 304 (未修改) 自從上次請求后尸诽,請求的網(wǎng)頁未修改過。 服務器返回此響應時教馆,不會返回網(wǎng)頁內容逊谋。
    + 305 (使用代理) 請求者只能使用代理訪問請求的網(wǎng)頁。 如果服務器返回此響應土铺,還表示請求者應使用代理胶滋。
    + 307 (臨時重定向) 服務器目前從不同位置的網(wǎng)頁響應請求,但請求者應繼續(xù)使用原有位置來進行以后的請求悲敷。

  • 4xx(請求錯誤) 這些狀態(tài)代碼表示請求可能出錯究恤,妨礙了服務器的處理。
    + 400 (錯誤請求) 服務器不理解請求的語法后德。
    + 401 (未授權) 請求要求身份驗證部宿。
    + 403 (禁止) 服務器拒絕請求。
    + 404 (未找到) 服務器找不到請求的網(wǎng)頁瓢湃。
    + 405 (方法禁用) 禁用請求中指定的方法理张。
    + 406 (不接受) 無法使用請求的內容特性響應請求的網(wǎng)頁。
    + 407 (需要代理授權) 此狀態(tài)代碼與 401(未授權)類似绵患,但指定請求者應當授權使用代理雾叭。
    + 408 (請求超時) 服務器等候請求時發(fā)生超時。
    + 409 (沖突) 服務器在完成請求時發(fā)生沖突落蝙。 服務器必須在響應中包含有關沖突的信息织狐。
    + 410 (已刪除) 如果請求的資源已永久刪除,服務器就會返回此響應筏勒。
    + 411 (需要有效長度) 服務器不接受不含有效內容長度標頭字段的請求移迫。
    + 412 (未滿足前提條件) 服務器未滿足請求者在請求中設置的其中一個前提條件。
    + 413 (請求實體過大) 服務器無法處理請求管行,因為請求實體過大厨埋,超出服務器的處理能力。
    + 414 (請求的 URI 過長) 請求的 URI(通常為網(wǎng)址)過長捐顷,服務器無法處理揽咕。
    + 415 (不支持的媒體類型) 請求的格式不受請求頁面的支持悲酷。
    + 416 (請求范圍不符合要求) 如果頁面無法提供請求的范圍,則服務器會返回此狀態(tài)代碼亲善。
    + 417 (未滿足期望值) 服務器未滿足”期望”請求標頭字段的要求设易。

  • 5xx(服務器錯誤) 這些狀態(tài)代碼表示服務器在嘗試處理請求時發(fā)生內部錯誤。
    + 500 (服務器內部錯誤) 服務器遇到錯誤蛹头,無法完成請求顿肺。
    + 501 (尚未實施) 服務器不具備完成請求的功能。
    + 502 (錯誤網(wǎng)關) 服務器作為網(wǎng)關或代理渣蜗,從上游服務器收到無效響應屠尊。
    + 503 (服務不可用) 服務器目前無法使用(由于超載或停機維護)。 通常耕拷,這只是暫時狀態(tài)讼昆。
    + 504 (網(wǎng)關超時) 服務器作為網(wǎng)關或代理,但是沒有及時從上游服務器收到請求骚烧。
    + 505 (HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協(xié)議版本浸赫。

  • http頭:

    • 設置語言
           Accept - language:zh-CN, jp;q=0.8
      
    • 斷點續(xù)傳
        Content-Rang:bytes 0-5/total
      
    • 防盜鏈(referer)
        let refererHost = url.parse(req.headers['referer']).host;
        let  host = req.headers['host']
        if(refererHost != host){
            不是同一網(wǎng)站
        }
      
    • 壓縮
        zlib核心包 
        fs.createReadStream(path).pipe(zilb.createGzip()).pipe(res)
      
  • 高階函數(shù) (callback)解決異步問題 并發(fā) 基于回調(回調地獄 錯誤處理很復雜)

  • promise原理(必會 手寫源碼)

  • defer 實現(xiàn)defer的延遲對象(必會)

  • promise的優(yōu)缺點:

    • 解決回調地獄 鏈式調用
  • co + generator (saga) yield *

  • async + await

  • es6

    • 箭頭函數(shù)(沒有this argument prototype) 原型鏈 各種繼承
    • 解構 模板字符串 剩余運算符
    • 遞歸拷貝 + 解決循環(huán)應用 weakmap
    • Set,Map(去重 交差補) Symbol instanceof
    • Object.defineProperty -> proxy(解決數(shù)組問題 觸發(fā)兩次)+reflect 遞歸
    • class
  • eventloop事件環(huán)

    • 宏任務: settimeout messageCheenl setimmidate UI線程
    • 微任務:promise.then mutationobserver nexttick
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末赃绊,一起剝皮案震驚了整個濱河市既峡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碧查,老刑警劉巖运敢,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忠售,居然都是意外死亡传惠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門稻扬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涉枫,“玉大人,你說我怎么就攤上這事腐螟。” “怎么了困后?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵乐纸,是天一觀的道長。 經(jīng)常有香客問我摇予,道長汽绢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任侧戴,我火速辦了婚禮宁昭,結果婚禮上跌宛,老公的妹妹穿的比我還像新娘。我一直安慰自己积仗,他們只是感情好疆拘,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寂曹,像睡著了一般哎迄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隆圆,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天漱挚,我揣著相機與錄音,去河邊找鬼渺氧。 笑死旨涝,一個胖子當著我的面吹牛,可吹牛的內容都是我干的侣背。 我是一名探鬼主播白华,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秃踩!你這毒婦竟也來了衬鱼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤憔杨,失蹤者是張志新(化名)和其女友劉穎鸟赫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體消别,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡抛蚤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寻狂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岁经。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蛇券,靈堂內的尸體忽然破棺而出缀壤,到底是詐尸還是另有隱情,我是刑警寧澤纠亚,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布塘慕,位于F島的核電站,受9級特大地震影響蒂胞,放射性物質發(fā)生泄漏图呢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛤织。 院中可真熱鬧赴叹,春花似錦、人聲如沸指蚜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姚炕。三九已至摊欠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柱宦,已是汗流浹背些椒。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掸刊,地道東北人免糕。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像忧侧,于是被迫代替她去往敵國和親石窑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容