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 `<ul>
        ${info.map(item => showInfo`<li>名字:${item.name},年龄:${item.age}</li>`).join('')}
    </ul>`
}

function showInfo(strings, ...args){
    console.log(strings)    
    // ["<li>名字:", ",年龄:", "</li>", 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 库使用

<script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js"></script>

<script>
    // 时间戳格式化为时间
    var res = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
    console.log(res)        // 2020-3-24 17:59:34

    console.log(moment().format("YYYY-MM-DD HH:mm:ss"))     // 2020-3-24 17:59:34

    const date = moment("1999-06-27 10:04:35")
    console.log(date.format("YYYY-MM-DD HH:mm:ss"))         // 1999-06-17 10:04:35
    console.log(date.add(10,"days")format("YYYY-MM-DD HH:mm:ss")) // 1999-06-27 10:04:35
</script>


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数据绑定

<input type="text" v-model="inp" />
<input type="text" v-model="title" />  输入 123
<input type="text" v-model="title" />
<h2 v-bind="title"></h2>
<script>
    function View(){
        let proxy = new Proxy({},{
            get(obj,property){},
            set(obj,property,value){
                console.log(property)   // title / inp
                console.log(value)      // 123 (v-model == title / inp 输入框输入的值)
                document.querySelectAll(`[v-model = "${property}"]`).forEach(item => {
                    item.value = value
                })
                document.querySelectAll(`[v-bind = "${property}"]`).forEach(item => {
                    item.value = value
                })
            }
        })
        this.init = () => {
            const els = document.querySelectAll("[v-model]")
            els.forEach(item=>{
                item.addEventListener('keyup',()=>{
                    // proxy['title'] = item.value   触发proxy的set
                    proxy[this.getAttribute('v-model')] = this.value
                })
            })
        }
    }
    new View.init()
    
</script>


使用Proxy验证表单组件

<input type="text" validate rule="max:12,min:3" />
<input type="text" validate rule="max:3,isNumber" />

<script>
    "use strict"
    class Validate{
        max(value,len){
            return value.length <= len
        }
        min(value,len){
            return value.length >= len
        }
        isNumber(value){
            return /^\d+$/.test(value)
        }
    }
    
    function ProxyFactory(target){
        return new Proxy(target,{
            get(target,key){
                return target[key]
            },
            set(target,key,el){ // el 为表单元素
                // 获取规则
                const rule = el.getAttribute("rule")
                // 验证类
                const validate = new Validate()
                let state = rule.split(",").every(rule =>{
                    const info = rule.split(":")
                    // 返回结果
                    return validate[info[0]](el.value,info[1])
                })
                return true
            }
        })
    }
    
    // 找到需要验证的表单组件
    const els = document.querySelectorAll("[validate]")
    const proxy = ProxyFactory(els)
    proxy.forEach((item,i) =>{
        item.onkeyup = ()=>{
            proxy[i] = this
        }
    })
</script>


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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341