跳至主要內容
Emoji 表情报自取
😁😀😂😃😄😅😆😉😊😋😎😍😘😗😙😚🙂🤗🤔😐😑😶🙄😏😣😥😮🤐😯😪😫😴😌😛😜😝😒😓😔😕🙃🤑😲🙁😖😞😟😤😢😭😦😧😨😩😬😰😱😳😵😡😠😷🤒🤕😇🤓😈👿👹👺💀👻👽👾🤖💩😺😸😹😻😼😽🙀😿😾🙈🙉🙊👶👦👧👨👩👴👵👮💂👷👸👳👲👱👰👼🎅🙍🙎🙅🙆💁🙋🙇💆💇🚶🏃💃👯🛀🛌👤👥🏇🏂🏄🚣🏊🚴🚵👫👬👭💏💑👨👩👦💪👈👉👆🖕👇🖖🤘✋👌👍👎✊👊👋👏👐🙌🙏💅👂👃👣👀👅👄💋💘💓💔💕💖💗💙💚💛💜💝💞💟💌💤💢💣💥💦💨💫💬💭👓👔👕👖👗👘👙👚👛👜👝🎒👞👟👠👡👢👑👒🎩🎓📿💄💍💎

  

🐵🐒🐶🐕🐩🐺🐱🐈🦁🐯🐅🐆🐴🐎🦄🐮🐂🐃🐄🐷🐖🐗🐽🐏🐑🐐🐪🐫🐘🐭🐁🐀🐹🐰🐇🐻🐨🐼🐾🦃🐔🐓🐣🐤🐥🐦🐧🐸🐊🐢🐍🐲🐉🐳🐋🐬🐟🐠🐡🐙🐚🦀🐌🐛🐜🐝🐞🦂💐🌸💮🌹🌺🌻🌼🌷🌱🌲🌳🌴🌵🌾🌿🍀🍁🍂🍃

  

🍇🍈🍉🍊🍋🍌🍍🍎🍏🍐🍑🍒🍓🍅🍆🌽🍄🌰🍞🧀🍖🍗🍔🍟🍕🌭🌮🌯🍳🍲🍿🍱🍘🍙🍚🍛🍜🍝🍠🍢🍣🍤🍥🍡🍦🍧🍨🍩🍪🎂🍰🍫🍬🍭🍮🍯🍼☕🍵🍶🍾🍷🍸🍹🍺🍻🍴🔪🏺

  

🎃🎄🎆🎇✨🎈🎉🎊🎋🎍🎎🎏🎐🎑🎀🎁🎫🏆🏅⚽⚾🏀🏐🏈🏉🎾🎱🎳🏏🏑🏒🏓🏸🎯⛳🎣🎽🎿🎮🎲🃏🀄🎴

  

🌍🌎🌏🌐🗾🌋🗻🏠🏡🏢🏣🏤🏥🏦🏨🏩🏪🏫🏬🏭🏯🏰💒🗼🗽⛪🕌🕍🕋⛲⛺🌁🌃🌄🌅🌆🌇🌉🌌🎠🎡🎢💈🎪🎭🎨🎰🚂🚃🚄🚅🚆🚇🚈🚉🚊🚝🚞🚋🚌🚍🚎🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🚚🚛🚜🚲🚏⛽🚨🚥🚦🚧⚓⛵🚤🚢🛫🛬💺🚁🚟🚠🚡🚀🚪🚽🚿🛁⌛⏳⌚⏰🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜🌝🌞⭐🌟🌠⛅🌀🌈🌂☔⚡⛄🔥💧🌊

  

🔇🔈🔉🔊📢📣📯🔔🔕🎼🎵🎶🎤🎧📻🎷🎸🎹🎺🎻📱📲📞📟📠🔋🔌💻💽💾💿📀🎥🎬📺📷📸📹📼🔍🔎🔬🔭📡💡🔦🏮📔📕📖📗📘📙📚📓📒📃📜📄📰📑🔖💰💴💵💶💷💸💳💹💱💲📧📨📩📤📥📦📫📪📬📭📮📝💼📁📂📅📆📇📈📉📊📋📌📍📎📏📐🔒🔓🔏🔐🔑🔨🔫🏹🔧🔩🔗💉💊🚬🗿🔮

  

🏧🚮🚰♿🚹🚺🚻🚼🚾🛂🛃🛄🛅🚸⛔🚫🚳🚭🚯🚱🚷📵🔞🔃🔄🔙🔚🔛🔜🔝🛐🕎🔯♈♉♊♋♌♍♎♏♐♑♒♓⛎🔀🔁🔂⏩⏪🔼⏫🔽⏬🎦🔅🔆📶📳📴🔱📛🔰

  

⭕✅❌❎➕➖➗➰➿❓❔❕❗🔟💯🔠🔡🔢🔣🔤🆎🆑🆒🆓🆔🆕🆖🆗🆘🆙🆚🈁🈶🈯🉐🈹🈚🈲🉑🈸🈴🈳🈺🈵◽◾⬛⬜🔶🔷🔸🔹🔺🔻💠🔘🔲🔳⚪⚫🔴

yyshino小于 1 分钟otherJS
WeakMap与Map的区别

WeakMap与Map的区别

WeakMap

  1. key必须是对象
  2. key是弱引用
弱引用与强引用
  • 弱引用:不会影响垃圾回收机制。即: WeakMap 的 key 不再存在任何引用时,会被直接回收。

  • 强引用:会影响垃圾回收机制。存在强应用的对象永远不会被回收。

对比示例

<script>

    let obj1 = {
        name: '张三'
    }
    let obj2 = {
        name: '张三'
    }

    // 强引用
    const map = new Map()
    // 弱引用
    const weakMap = new WeakMap()
    map.set(obj1,'value')
    weakMap.set(obj2,'value')

    obj1 = null
    obj2 = null

    console.log('map',map) // Map(1) {{…} => 'value'}
    console.log('weakMap',weakMap) // WeakMap {} 空
    
    /**
    此时 WeakMap 中不存在任何值,即: obj2不存在其他引用时, WeakMap 不会阻止垃圾回收,基于obj2的引用将会被清除。这就证明了 WeakMap 的 弱引用特性。
    */
</script>

yyshino小于 1 分钟FrontEndJS
手写reduce

MDN参考

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

语法

reduce(callbackFn)
reduce(callbackFn, initialValue)

yyshino大约 2 分钟FrontEndJS手写系列
手写call、apply、bind

手写call、apply、bind

总结

  • 三者都可以改变函数的this对象指向
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefinednull,则默认指向全局window
  • 三者都可以传参,但是apply是数组,而call是参数列表,且applycall是一次性传入参数,而bind可以分为多次传入
  • bind是返回绑定this之后的函数,applycall 则是立即执行

yyshino大约 2 分钟FrontEndJS手写系列
并发请求
    /**
     * 在某些场景下,页面的请求数可能会有很多,
     * 比如:抓取、分片上传等,如果我们需要等一个请求完成后,
     * 再发起下一个请求,是必效率会比较低。
     * 为了提升效率,我们可以同时发出多个请求,但数量又不能太多,
     * 如若某请求完成,剩余等待的请求继续补位执行,
     * 将请求的结果(不论成功或失败),按原有数组的顺序返回。
     */

    /**
     * 11-并发事件
     * @param {string[]} urls 请求地址数组
     * @param {number} max 最大并发数
     */
    function consurRequest(urls, max) {
        return new Promise((resolve,reject) => {
            // 判断传入urls长度,为空直接返回[]
            if(urls.length === 0){
                resolve([])
                return
            }

            const results = []
            let count = 0 // 标识请求的完成数量
            let index = 0 // 下一个请求

            // 发送请求
            async function request(){
                // 退出逻辑
                if(index === urls.length){
                    return
                }

                // 存储 index,保持后续请求结果数组与urls数组对应
                const i = index
                const url = urls[index]
                index++
                try {
                    const resp = await fetch(url)
                    // resp加入到 results中
                    results[i] = resp
                } catch (err) {
                    // err 加入到results
                    results[i] = err
                    console.log('err',err)
                } finally {
                    // 判断是否所以的请求都完成
                    count++
                    // if(count === urls.length){
                    if(count === urls.length){
                        resolve(results)
                        return
                    }
                    request()
                }
            }

            const times = Math.min(max,urls.length)
            let promiseList = []

            for(let i = 0; i < times; i++){
                promiseList.push(request())
            }

            Promise.race(promiseList).then(() => {
            }).catch((err) => {
                reject(err)
            })
        })
    }

yyshino大约 1 分钟FrontEndJS手写系列
Vue响应式实现

原理

ProxyObject.defineProperty

  1. Proxy
    1. Proxy 将代理一个对象(被代理对象),得到一个新的对象(代理对象),同时拥有被代理对象中所有的属性。
    2. 当想要修改对象的指定属性时,我们应该使用代理对象进行修改
    3. 代理对象 的任何一个属性都可以触发 handlergettersetter
  2. Object.defineProperty
    1. Object.defineProperty 为指定对象的指定属性设置属性描述符
    2. 当想要修改对象的指定属性时,可以使用原对象进行修改
    3. 通过属性描述符,只有 被监听 的指定属性,才可以触发 gettersetter

yyshino大约 2 分钟FrontEndJS
手写Promise相关方法

Promise.all

特点:

  • Promise.all() 方法接收一个promise的iterable类型(MDN)
  • 只返回一个promise实例
  • 当传入的参数promise全部成功时,最后的结果才会成功(成功的结果是所有的promise的成功的结果组成的数组),只要有一个promise失败,all返回的实例就是一个失败的promise(失败的结果是传入的参数中的第一个失败的promise的结果)
let p1 = new Promise(resolve => {
    setTimeout(resolve, 200, 1)
});
let p2 = new Promise((resolve, reject) => reject(2));
let p3 = 3;
console.log(Promise.all([p1, p2, p3]));//all方法
let myAll = function(parr) {
    let result = [],//最后成功的结果
        count = 0,//累加器,与len比较判断是否全部成功了
        len = parr.length;
    return new Promise((resolve, reject) => {
        for (let p of parr) {// 依次测试传入的参数(转化为promise)是否是成功的
            Promise.resolve(p).then(res => {
                result[count] = res;// 成功就加入到结果中
                count++;// 累加器加一
                if (count == len) {// 如果相等,说明都成功了,可以走成功resolve
                    resolve(res);
                }
            }, err => {
            // 只要有一个失败了,直接走失败reject
                reject(err);
            })
        }
    })
}
console.log(myAll([p1, p2, p3]));

yyshino大约 3 分钟FrontEndJS手写系列
手写常用排序算法

冒泡排序

在未排序区域中,从前向后不断对比相邻数据,将较大值不断向后移动,直至移动到未排序区域的最后一位。

    const arr = [2, 44, 1, 0, -22, 56, -78];
    // arr.sort((a,b)=>a-b)
    function bubbleSort(arr){
        let tmp;
        for(let i=arr.length; i>0; i--){// 较大的arr[j]会冒泡到arr的尾部
            for(let j=0; j<i-1; j++){
                if(arr[j]>arr[j+1]){// 前一个元素比或一个大,则向后冒泡(交换)
                    tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
        return arr;
    }
    console.log(bubbleSort(arr));// [-78, -22, 0, 1, 2, 44, 56]

yyshino大约 4 分钟FrontEnd算法JS算法