美文网首页日常刻书
一些常用的代理陷阱函数(六)

一些常用的代理陷阱函数(六)

作者: F_wind | 来源:发表于2021-02-19 15:46 被阅读0次

    《深入理解ES6》阅读随笔

    数组代理

    在 ES6 之前,在 JavaScript 中是无法直接创建数组对象的,但是在 ES6 中,可以通过代理的方式来模拟实现一个数组对象。

    数组到底实现了什么功能

    数组是一个可以动态增减元素并且实时更新数组长度 length 的对象,下面是一个简单的实现案例:

    let arr = new Array(2)
    console.log(arr.length) // 2
    arr[0] = 'a'
    arr[1] = 'b'
    arr[2] = 'c'
    console.log(arr) // [ 'a', 'b', 'c']
    console.log(arr.length) // 3
    console.log(arr[1]) // a
    arr.length = 1
    console.log(arr.length) // 1
    console.log(arr[1]) // undefined
    

    从上面的例子中可以归纳出:

    1. 当给数组索引赋值时,如果该索引已存在,那么值更新,如果赋值大于数组长度,那么还需要更新 length;
    2. 当直接修改 length 时,如果赋值元素比数组长度长,那么只需更新 length,如果赋值元素比数组长度短时,还需要删除原来多出来的那部分元素。
    检索数组索引

    判断新的键是否满足数组索引键的条件:

    function toUnit32(value) {
        return Math.floor(Math.abs(Number(value)) % Math.pow(2, 32))
    }
    
    function isArrayIndex(key) {
        const numericKey = toUnit32(key)
        return numericKey == String(numericKey) && numericKey < (Math.pow(2, 32) - 1)
    }
    
    新增元素 length 递增和设置 length 删除元素

    通过代理创建类数组对象:

    function toUnit32(value) {
        return Math.floor(Math.abs(Number(value)) % Math.pow(2, 32))
    }
    
    function isArrayIndex(key) {
        const numericKey = toUnit32(key)
        return numericKey == String(numericKey) && numericKey < (Math.pow(2, 32) - 1)
    }
    
    function createArray(length = 0) {
        return new Proxy({
            length
        }, {
            set(trapTargat, key, value) {
                const currentLength = Reflect.get(trapTargat, 'length')
                if (isArrayIndex(key)) {
                    if (Number(key) >= currentLength) {
                        Reflect.set(trapTargat, 'length', currentLength + 1)
                    }
                } else if (key === 'length') {
                    if (value < currentLength) {
                        for (let i = currentLength - 1; i >= value; i--) {
                            Reflect.deleteProperty(trapTargat, i)
                        }
                    }
                }
                return Reflect.set(trapTargat, key, value)
            }
        })
    }
    
    const arr = createArray(2)
    console.log(arr.length) // 2
    arr[0] = 'a'
    arr[1] = 'b'
    arr[2] = 'c'
    console.log(arr.length) // 3
    console.log(arr[1]) // a
    arr.length = 1
    console.log(arr.length) // 1
    console.log(arr[1]) // undefined
    
    自定义代理数组类

    将代理实现类数组对象封装为一个类实现:

    function toUnit32(value) {
        return Math.floor(Math.abs(Number(value)) % Math.pow(2, 32))
    }
    
    function isArrayIndex(key) {
        const numericKey = toUnit32(key)
        return numericKey == String(numericKey) && numericKey < (Math.pow(2, 32) - 1)
    }
    
    class MyArray {
        constructor(length = 0) {
            this.length = length
    
            return new Proxy({
                length
            }, {
                set(trapTargat, key, value) {
                    const currentLength = Reflect.get(trapTargat, 'length')
                    if (isArrayIndex(key)) {
                        if (Number(key) >= currentLength) {
                            Reflect.set(trapTargat, 'length', currentLength + 1)
                        }
                    } else if (key === 'length') {
                        if (value < currentLength) {
                            for (let i = currentLength - 1; i >= value; i--) {
                                Reflect.deleteProperty(trapTargat, i)
                            }
                        }
                    }
                    return Reflect.set(trapTargat, key, value)
                }
            })
        }
    }
    
    const arr = createArray(2)
    console.log(arr.length) // 2
    arr[0] = 'a'
    arr[1] = 'b'
    arr[2] = 'c'
    console.log(arr.length) // 3
    console.log(arr[1]) // a
    arr.length = 1
    console.log(arr.length) // 1
    console.log(arr[1]) // undefined
    

    相关文章

      网友评论

        本文标题:一些常用的代理陷阱函数(六)

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