JS随手笔记

传值与传地址

// 传值,两个变量指针指向不同对象
let a = 1
let b = a
b = 2
console.log(a,b)    // 1 2

// 传址,两个变量指针指向同一对象或数组
let a = {name:'kevin'}
let b = a
b.name = 'jeff'
console.log(a,b)    // jeff jeff

严格模式

**use strict ** 只对当前作用域及子作用域有效

严格模式下使用的变量必须定义


break-continue 与 label使用

label:for(let i = 0; i < 10; i++){
    if(i == 5){
        continue label
    }
}

typeof instanceof

let a = []
let b = {}
console.log(typeof a)   // object
console.log(typeof b)   // object

console.log(a instanceof Array)         // true
console.log(a instanceof Object)        // false
console.log(b instanceof Object)        // true

function User(){}

let c = new User()
console.log(typeof c)       // object
console.log(c instanceof User)      //true
console.log(c instanceof Object)    //true


标签模板实例操作

const info = [
    {name:'张三',age:18},
    {name:'李四',age:19},
    {name:'王五',age:20}
]

function template(){
    return `
    ${info.map(item => showInfo`
  • 名字:${item.name},年龄:${item.age}
  • `).join('')}
` } function showInfo(strings, ...args){ console.log(strings) // ["
  • 名字:", ",年龄:", "
  • ", raw: Array(3)] * 3 console.log(args) // ["张三", 18] // ["李四", 19] // ["王五", 20] return strings.map((val,key) => { return val + (args[key] ? args[key] : "") }).join("") } document.body.innerHTML = template()

    Object.is(val1,val2) / NaN

    let arr = [1]
    console.log(Number(arr))    // 1
    let arr2 = [1,2]
    console.log(Number(arr2))   // NaN
    
    console.log(2 / 'a')        // NaN
    console.log(NaN == NaN)     // false
    console.log(Number.isNaN(2 / 'a'))      // true
    console.log(Object.is(2 / 'a',NaN))     // true
    

    new Date / Date

    const d1 = new Date()
    console.log(d1)                 // Tue Mar 24 2020 17:16:00 GMT+0800 (中国标准时间)
    console.log(new Date() * 1)     // 1585041382989
    console.log(typeof d1)          // object
    
    const d2 = Date()
    console.log(d2)                 // Tue Mar 24 2020 17:16:00 GMT+0800 (中国标准时间)
    console.log(new Date() * 1)     // NaN
    console.log(typeof d2)          // string
    
    // 获取时间戳
    console.log(Date.now())         // 1585041382989
    console.log(new Date() * 1)
    console.log(new Date().valueOf())
    console.log(new Date().getTime())
    console.log(Number(new Date()))
    
    // 时间戳转时间
    console.log(Date.now())         // Tue Mar 24 2020 17:16:22 GMT+0800 (中国标准时间)
    
    // 计算代码执行时间
    console.time("runTime")
    // any code
    console.timeEnd("runTime")      // runTime: 11.8548555567ms
    
    // 自定义时间
    const d3 = new Date("1999-9-16 5:15:20")
    const d4 = new Date(1999,9,16,5,15,20)
    console.log(d3)         // Thu Sep 16 1999 05:15:20 GMT+0800 (中国标准时间)
    console.log(d4)         // Thu Sep 16 1999 05:15:20 GMT+0800 (中国标准时间)
    
    

    时间格式化函数封装

    function dateFormat(date,format = "YYYY-MM-DD HH:mm:ss"){
        const config = {
            YYYY: date.getFullYear(),
            MM: date.getMonth(),
            DD: date.getDate(),
            HH: date.getHours(),
            mm: date.getMinutes(),
            ss: date.getSeconds()
        }
        for(const key in config){
            format = format.replace(key,config[key])
        }
        return format
    }
    
    let date = new Date()
    console.log(dateFormat(date,"YYYY年MM月DD日"))
    
    

    moment.js 库使用

    
    
    
    
    

    Array.from

    const str = "abcde"
    let resArr = str.split('');         // ["a","b","c","d","e"]
    console.log(Array.from(str))        // ["a","b","c","d","e"]
    
    const divs = document.querySelectAll('div')
    // 转换为数组
    Array.from(divs)
    // 转换为数组,并进行操作
    Array.from(divs,(item)=>{
        // item 为循环每个dom对象
    })
    
    

    toggle

    dom.classList.toggle("className") // 原生 js 切换类名


    数组方法

    // fill     填充
    let arr = [1,2,3,4,5]
    console.log(Array(3).fill('a'))     //['a','a','a']
    arr.fill('a',2,4)       // [1,'a','a',4,5]
    
    // push,unshift(头部添加) 返回值为数组长度
    
    // pop,shift(头部移除) 返回值为该元素
    
    // splice(a,b,c)  a:起始位置, b:移除数量, c:替换的数据
    // 会改变原数组
    let tempArr = arr.splice(0,3)
    console.log(tempArr)        // [1,2,3]
    console.log(arr)            // [4,5]
    let arr2 = [1,2,3,4,5]
    arr2.splice(1,0,'a')        // [1,'a',2,3,4,5]
    
    // copyWithin(a,b,c)    a:起始替换位置, b:复制起始位置, c:复制结束位置 [b,c)
    let arr3 = [1,2,3,4,5]
    console.log(arr3.copyWithin(2,1,3))     // [1, 2, 2, 3, 5]
    
    // find(callback) 、 findIndex(callback) -> 返回下标值
    let arr4 = [1,2,3,4,5]
    let obj = {{name:'zhangsan'},{name:'lisi'},{name:'wangwu'}}
    let res = arr.find(item => {return item === 3})     // 3 (值),   没找到返回 undefined
    let res2 = obj.find(item => {return item.name === 'lisi'})      // {name:'lisi'} (值)
    
    // sort(callback)   callback 返回值为负数(从小到大)  正数(从大到小)
    
    // keys()、values()、entries()
    let arr5 = ['a','b','c']
    let keys = arr5.keys()
    let { value, done } = keys.next()       // 0 (下标)    false (false表示没迭代完)
    console.log(keys.next())        // {value: 1, done: false}
    console.log(keys.next())        // {value: 2, done: false}
    console.log(keys.next())        // {value: undefined, done: true}
    
    while(({ value, done } = values.next()) && done === false){
        console.log(value)      // a,b,c
    }
    
    // entries 为 keys()、value() 集合
    let entries = arr5.entries()
    let {done,value:[index,value]} = entries.next()
    console.log(index,value)    // 0 "a"
    
    for(let [key,value] of arr.entries()){
        console.log(key,value)      // 0 "a"
    }
    
    // every 判断是否全部符合(一个错误, 跳出循环)
    // some 任意符合(一个正确, 跳出循环)
    let arr6 = [1,2,3,4,5]
    let res1 = arr6.every((value,index,arr)=>{
        return value > 0
    })
    
    let res2 = arr6.some((value,index,arr)=>{
        return value < 0
    })
    
    console.log(res1)       // true
    console.log(res2)       // false
    
    

    Symbol(生成一个不会重复的字符串)

    let a = Symbol()
    let b = Symbol()
    console.log(typeof a)       // symbol
    console.log(a == b)         // false
    
    // 注意: Symbol不可以添加属性
    
    // 第一种定义, 如果描述内容一样, 内容地址不一样, 会重复创建
    let c = Symbol('我是描述信息')
    console.log(c.description)      // 我是描述信息
    
    // 第二种定义, 如果描述内容一样, 内容地址一样, 不会重复创建
    let d = Symbol.for('test')
    let e = Symbol.for('test')
    console.log(d == e)     // true
    console.log(Symbol.keyFor(d))       // test
    console.log(Symbol.keyFor(c))       // undefined
    
    let fs = Symbol("描述")
    let f = {
        name: "kevin",
        age: "18",
        [fs]: "any"
    }
    
    // 循环遍历不到Symbol (遍历不到 fs)
    
    // 只遍历Symbol
    for(const key of Object.getOwnPropertSymbols()){
        console.log(key)    // Symbol(描述)
    }
    
    

    set

    方法 / 属性 解释 返回值
    size set 长度 数量
    has(item) 是否包含item boolean
    delete(item) 删除item boolean
    values() 展示全部元素 SetIterator {item1,item2 ...}
    clear() 清除所有元素 undefined
    add(item) 添加元素 Set
    let set = new Set()
    set.add(1)
    set.add(1)
    console.log(set)        // Set(1) {1}
    
    // new Set(Array)
    let a = new Set([1,2,3])
    console.log(a)      // Set(3) {1,2,3}
    
    // set 转数组
    console.log([...a])             // [1,2,3]
    console.log(Array.from(a))      // [1,2,3]
    
    
    // new Set(String)
    console.log(new Set("hello"))       // Set(5) {"h","e","l","l","o"}
    
    let b = {}
    let c = { [b]: 'b' }
    console.log(c)                          // {[object Object]: "b"}
    console.log(b.toString())               // [object Object]
    console.log(c["[object Object]"])       // b
    
    
    // Set 遍历 value 与 key 一样
    set.forEach((value,key,set)=>{})
    for(const value of set){}
    
    // 并集、交集、差集
    let d1 = new Set([1,2,3,4,5])
    let d2 = new Set([1,3,6,7,4])
    // 并集
    console.log(new Set([...d1,...d2]))     // Set(7) {1,2,3,4,5,6,7}
    // 差集
    console.log(new Set([...d1].filter(item => !d2.has(item))))   // Set(7) {2,5}
    // 交集
    console.log(new Set([...d1].filter(item => d2.has(item))))    // Set(7) {1,3,4}
    

    Map

    方法 / 属性 解释 返回值
    size set 长度 数量
    has(key) 是否包含key boolean
    delete(key) 删除key对应的项 boolean
    values() 展示全部value MapIterator {value1,value2...}
    clear() 清除所有元素 undefined
    set(key,value) 添加元素 Map
    let map = new Map()
    
    // 添加元素1    map.set(key,value)
    map.set("name","kevin")
    // 添加元素2    new Map([[key,value],[...],...])
    let map2 = new Map([[key,value],[key2,value2],...])
                        
    // Map 遍历 
    map.forEach((value,key)=>{})
    for(const [key,value] of map.entries()){}
    
    // Map 转换 Array
    console.log([...map])
    console.log([...map.values()])
    

    this

    对象中函数(一层)的this指向该对象

    箭头函数中,this指向上层对象的this

    普通函数,this指向window


    apply、call、bind

    call ( this , v1 , v2 , ... )

    apply ( this , [ v1, v2, ...] )

    call apply 会立即执行

    bind 会返回一个新的函数,不会立即执行

    bind 可以直接传参数,也可以间接调用新函数时传参数,参数会累积

    function A(a,b){
        console.log(a,b)
        return this.c + a + b
    }
    
    console.log(A.call({c:5},1,2))  // a=1, b=2, c=3
    let func = A.bind({c:5},1,2)    
    console.log(func())     // a=1, b=2, c=3
    
    let func = A.bind({c:5},1)  
    console.log(func(2))// a=1, b=2, c=3
    
    

    obj/array.hasOwnProperty("key")

    判断该key(属性)是否在obj / array 对象( 排除原型链 )中,返回值为boolean

    拓展:“key” in obj / array 判断属性key是否在obj / array 中(包含原型链)


    Object.setPrototypeOf(对象,对象的原型)

    设置对象的原型

    let a = {name:"kevin"}
    let b = {name:"jeff'"}
    Object.setPrototypeOf(a,b)
    console.log(a.__proto__)    // {name: "jeff'"}
    

    Object.assign(obj1,obj2,...)

    将obj2覆盖obj1中的相同项,并返回一个新的对象

    let a = {name:'kevin',akey:'a'}
    let b = {name:'jeff',age:18}
    let c = {ckey:'c'}
    let d = Object.assign(a,b,c)
    console.log(d) // {name: "jeff", akey: "a", age: 18, ckey: "c"}
    

    JSON

    JSON.stringify(a,b,c) 转换成json格式

    • a: obj / arr
    • b: 要保留的属性 , 格式 ["key1","key2",...] , null表示全部保留
    • c: tab键的空格数 number 类型

    JSON.parse(json,callback) json 转换成js对象格式

    • callback(key,value)
    let a = {
        name:'kevin',
        age:'18',
        toJSON:function(){
            return {
                name:"自定义的JSON格式"
            }
        }
    }
    let b = ["name","age"]
    console.log(JSON.stringify(a,null,2))
    /*
    {
      "name": "kevin",
      "age": "18"
    }
    */
    console.log(cJSON.stringify(a))     // {"name":"自定义的JSON格式"}
    console.log(JSON.stringify(b))      // ["name","age"]
    
    let json = JSON.stringify(a,null,2)
    let o = JSON.parse(json,(key,value)=>{
        console.log(key,value)
    })
    
    
    

    对象的深浅拷贝

    1. Object.assign(obj1,obj2,...) 浅拷贝
    2. {...obj} 深拷贝
    
    let obj = {
        name:'kevin',
        user:{
            name:'jeff'
        },
        arr:[]
    }
    
    // 浅拷贝
    function copy(obj){
        let res = {}
        for(const key in obj){
            res[key] = obj[key]     // 出现问题: obj.user 依旧是地址赋值
        }
        return res
    }
    
    // 深拷贝 (浅拷贝 + 递归)
    function deepCopy1(obj){
        let res = {}
        for(const key in obj){
            // 出现问题: arr:[] 变成arr:{}
            res[key] = typeof obj[key] == 'object'?deepCopy1(obj[key]):obj[key]
        }
        return res
    }
    
    // 深拷贝2 (浅拷贝 + 递归)
    function deepCopy2(obj){
        // 判断是数组还是对象
        let res = obj instanceof Array ? [] : {}
        for(const [k,v] of Object.entries(obj)){
            res[k] = typeof v == "object" ? deepCopy2(v) : v
        }
        return res
    }
    
    

    Object.getOwnPropertyDescriptor(obj,key)

    功能:查看对象属性的特征

    联想: 数组的 length 属性不能遍历

    let user = {
        name:'kevin',
        age:18
    }
    console.log(JSON.stringify(Object.getOwnPropertyDescriptor(user,name),null,2))
    /**
    {
      "value": "kevin",
      "writable": true,         // 可修改的
      "enumerable": true,       // 可遍历的
      "configurable": true      // 可删除或重新配置特征
    }
     */
    
    // 获取所有属性的特征
    Object.getOwnPropertyDescriptors(user)
    
    
    // 修改属性特征
    Object.getOwnPropertyDescriptor(user,'name').writable = false       // 错误的方式
    
    Object.defineProperty(user,"name",{     // 正确
        value: 'jeff',      // 修改属性值
        writable: false     // 修改属性特征
    })
    
    // 批量修改
    Object.defineProperties(user,{      
        key1:{
            
        },
        key2:{
            
        },
        ...
    })
    

    Object.preventExtensions(obj)

    禁止在对象obj中添加属性

    Object.isExtensible(obj):判断是否可以修改


    Object.seal(obj)

    功能:封闭对象,不允许任何操作属性的特征

    Object.isSeald(obj):判断对象特征是否封闭


    Object.freeze(obj)

    功能:冻结对象,只允许遍历

    Object.isFrozen(obj):判断是否冻结

    // 使用严格模式
    "use strict"
    
    const CONFIG = {
        url:"http://****"
    }
    Object.freeze(CONFIG)
    CONFIG.url = "any"      // 报错
    
    console.log(JSON.stringify(Object.getOwnPropertyDescriptor(CONFIG,url),null,2))
    /**
    {
      "value": "http://****",
      "writable": false,
      "enumerable": true,       // 可遍历
      "configurable": false
    }
    */
    

    访问器保护数据

    const user = {
        data:{name: "kevin", age: 18},
        // 设置属性访问器
        set age(age){
            if(typeof age != "number" || age >100 || age < 18){
                throw new Error("年龄更改错误")
            }
            this.data.age = age
        },
        // 获取属性访问器
        get age(){
            console.log(this.data.age)
        }
    }
    
    user.age = 20
    console.log(user.age)       // 20
    
    
    // get访问器伪造属性
    const user = {
        arr:[1,2,3,4,5],
        get total(){
            return this.arr.reduce((p,n) => p +n,0)
        }
    }
    console.log(user.total)     // 15
    user.total = 18     // 没有效果(没有set访问器), 严格模式报错
    

    访问器的优先级

    访问器的优先级高于普通属性

    提示:使用Symbol的唯一性作为对象的属性,外部无法更改内部属性

    const user = {
        name:'kevin',
        get name(){
            return '233'
        }
    }
    console.log(name)       // "233"
    
    

    token的读写处理

    let Request = {
        set token(content){
            localStorage.setItem('token',content)
        },
        get token(){
            let token = localStorage.getItem('token')
            !token ? return "请登录后操作" : return token
        }
    }
    
    // 设置token
    Request.token = "545453445556566656"
    console.log(Request.token)      // 545453445556566656
    
    

    Proxy 代理拦截

    // 基本使用
    // 对象代理
    const user = {name:"kevin"}
    const proxy = new Proxy(user,{
        set(obj,property,value){
            obj[property] = value
            return true
        },
        get(obj,property){
            console.log(obj,property)       // {name:"kevin"}       name
            return obj[property]            // kevin
        }
    })
    console.log(proxy.name)     // kevin
    proxy.name = 'jeff'
    console.log(proxy.name)     // jeff
    
    // 函数代理
    function add(a,b){
        return a + b
    }
    
    let proxy = new Proxy(add,{
        apply(func,obj,args){
            console.log(func,obj,args)      
            // func             当前函数对象
            // undefined        this指向
            // (2) [1, 2]       函数参数
            console.log(func.apply(this,args))      // 3
        }
    })
    proxy(1,2)
    proxy.apply({},[1,2])       // 改变this为{}
    
    

    Vue数据绑定

    
      输入 123
    
    


    使用Proxy验证表单组件

    
    
    
    
    
    

    instanceof

    原型检测

    in key in obj // 判断key属性是否在obj 或其原型链上

    hasOwnProperty(key) // 判断key属性是否在obj上

    function A(){}
    function B(){}
    let a = new A()
    let b = new B()
    console.log(a instanceof A)     // true
    A.prototype = b
    console.log(a instanceof B)     // true
    console.log(b instanceof A)     // false
    console.log(A.__proto__.constructor.prototype)          // B{}
    console.log(b.constructor.prototype == b.__proto__)     // true
    

    构造方法

    function User(name){
        this.name = name
    }
    User.prototype = {
        constructor: User,
        show(){
            console.log(this.name)
        },
        ...
    }
    
    let u = new User("kevin")
    u.show()        // kevin
    
    

    proto属性访问器

    proto设置为普通类型没有效果

    proto 中有get set访问属性

    const obj = {}
    obj.__proto__ = {
        show(){
            console.log("233")
        }
    }
    obj.show()  // 233 (向obj的原型添加show方法)
    obj.__proto__ = "233"   // 语句无效
    
    // 原理
    let obj = {
        action:{},
        get proto(){
            return this.active
        },
        set proto(obj){
            if(obj instanceof Object){
                this.action = obj
            }
        }
    }
    
    obj.proto = "abc"       // 无效
    obj.proto = {a:"abc"}       // 有效
    
    // 
    let obj = Object.create(null)       // 没有原型链
    obj.__proto__ = "abc"       // 成功
    
    

    原生继承的实现

    function extend(sub,sup){
        sub.prototype = Object.create(sup.prototype)
        Object.defineProperty(sub.prototype,"constructor",{
            value:sub,
            enumerable:false
        })
    }
    

    class

    class User{
        constructor(name){
            this.name = name
        }
        getName(){
            return this.name
        }
        setName(name){
            this.name = name
        }
    }
    
    let u = new User("kevin")
    console.log(u.getName())    // kevin
    
    

    静态方法

    static 定义,类名直接调用

    class User{
        show(){
            console.log("prototype show")
        }
        static show = function(){
            console.log("static show")
        }
    }
    
    User.show()     // static show
    new User.show() // prototype show
    
    

    私有属性

    class User{
        #name = 'kevin'
        constructor(age){
            this.age = age
        }
        show(){
            return #name
        }
        set name(name){
            this.name = name
        }
    }
    
    let u = new User(18)
    u.#name = "ccc"     // 报错,不允许修改私有属性
    u.name = "ccc"      // 修改私有属性
    
    

    class 继承

    class Fu{
        constructor(name){
            this.name = name
            console.log(name)
        }
    }
    
    class Zi extends Fu{
        constructor(name){
            super(name)
        }
    }
    
    let zi = new Zi("zhangsan")     // zhangsan
    

    原型继承

    function User(){}
    User.prototype.show = function(){
        console.log("func show")
    }
    
    function People(){}
    
    // 实现继承
    Admin.prototype = Object.create(User.prototype)
    let p = new People()
    p.show()    // func show
    

    super 原理

    new 子类时,自动调用父类构造方法 constructor

    如果子类没有定义constructor,默认constructor调用super

    子类如果定义了constructor,就必须调用super

    super必须放在子类赋值之前,放置父类属性覆盖子类属性

    方法、属性 同名,使用super.func()

    let a = {
        name:"a",
        show(){
            console.log("this is a")
            console.log(this.name)  // a
        }
    }
    let b = {
        name:"b",
        // 对象继承
        __proto__ : a,
        show(){
            // 执行父级方法
            this.__proto__.show.call(this)  // this is a    a
            console.log("this is b")
        }
    }
    b.show()
    

    静态继承原理

    function User(){
        User.name = "kevin",
        User.show = function(){
            console.log("User show")
        }
    }
    
    function P(){}
    P.__proto__ = User
    P.show()    // User show
    p.name      // kevin
    
    
    // class
    
    class User{
        static name = "kevin"
        static show(){
            console.log("User show")
        }
    }
    
    class P extends User{}
    console.log(P.name)     // kevin
    P.show()        // User show
    
    

    动画类

    class Animation {
        constructor(el) {
          this.el = el;
          this.timeout = 5;
          this.isShow = true;
          this.defaultHeight = this.height;
        }
        hide(callback) {
          this.isShow = false;
          let id = setInterval(() => {
            if (this.height <= 0) {
              clearInterval(id);
              callback && callback();
              return;
            }
            this.height = this.height - 1;
          }, this.timeout);
        }
        show(callback) {
          this.isShow = false;
          let id = setInterval(() => {
            if (this.height >= this.defaultHeight) {
              clearInterval(id);
              callback && callback();
              return;
            }
            this.height = this.height + 1;
          }, this.timeout);
        }
        get height() {
          return window.getComputedStyle(this.el).height.slice(0, -2) * 1;
        }
        set height(height) {
          this.el.style.height = height + "px";
        }
      }
      class Slide {
        constructor(el) {
          this.el = document.querySelector(el);
          this.links = this.el.querySelectorAll("dt");
          this.panels = [...this.el.querySelectorAll("dd")].map(
            item => new Panel(item)
          );
          this.bind();
        }
        bind() {
          this.links.forEach((item, i) => {
            item.addEventListener("click", () => {
              this.action(i);
            });
          });
        }
        action(i) {
          Panel.hideAll(Panel.filter(this.panels, i), () => {
            this.panels[i].show();
          });
        }
      }
      class Panel extends Animation {
        static num = 0;
        static hideAll(items, callback) {
          if (Panel.num > 0) return;
          items.forEach(item => {
            Panel.num++;
            item.hide(() => {
              Panel.num--;
            });
          });
          callback && callback();
        }
        static filter(items, i) {
          return items.filter((item, index) => index != i);
        }
      }
      let hd = new Slide(".s1");
    
    // 调用
    let dom = document.querySelector('.class')
    let a = new Animation(dom)
    
    a.hide(()=>{
        console.log("隐藏结束")
    })
    
    
    

    开发一个模块引擎

    let mudule = (function(){
        const moduleList = {}   // 模块容器
        // 模块名,依赖模块,模块动作
        function define(name,modules,action){
            modules.map((m,i)=>{
                modules[i] = moduleList[m]
            })
            moduleList[name] = action.apply(null,modules)
        }
        return { define }
    })()
    
    // 定义模块 a 
    mudule.define('a',[],function(){
        return {
            // 模块功能
            max(arr,key){
                return arr.sort((a,b)=>b[key]-a[key])[0]
            },
            min(arr,key){
                return arr.sort((a,b)=>a[key]-b[key])[0]
            }
        }
    })
    
    // b 模块依赖 a 模块
    module.define('b',['a'],function(a){
        let data = [
            {name:'js',price:199},
            {name:'mysql',price:233}
        ]
        console.log(a.max(data,'price'))    // {name:'js',price:199}
    })
    
    

    模块按需加载

    import 语法 返回promise ,不必写在最上层

    if(true){
        import("路径").then(({a,b})=>{
            console.log(a,b)
        })
    }
    

    promise 封装ajax

    function ajax(url){
        return new Promise((resolve,reject)=>{
            let xhr = new XHRHttpRequest()
            xhr = open("GET",url)
            xhr.send()
            xhr.onload = function(){
                if(this.status == 200){
                    resolve(this.response)
                }else{
                    reject(this.status)
                }
            }
            xhr.onerror = function(){
                reject(this)
            }
        })
    }
    

    缓存后台数据

    function query(name){
        const cache = query.cache || (query.cache = new Map())
        if(cache.has(name)){
            console.log("缓存了")
            return Promise.resolve(cache.get(name))
        }
        // 请求数据
        resolve ajax().then()
    }
    
    END

    你可能感兴趣的:(JS随手笔记)