JavaScript数组索引检测中的数据类型问题 4年前

之前在写微信小程序项目时,里面有一个“城市选择”的功能,笔者用的是 <picker-view> 组件,这个组件比较特别,因为它的 value 属性规定是 数组 格式的。比如: value="[1]"

因为当时对JS变量类型转换的不了解,笔者在代码中写下了这样的几行判断:(这是严谨的)

let val_one=typeof this.data.pIndex=="number"?[this.daya.pIndex]:this.data.pIndex

(:项目中存取元素是动态的!

上面这是因为要使下标动态跟随用户选择,并反馈到wxml里的 value 属性上展示。
但是在这之前还需要做一层判断 —— 因为有的地区是省级市或者直辖市,而且要防止用户“骚操作”,比如一直上拉或者猛的拉出去,这时候再微信小程序中是会报错找不到对应数据的:

let length=placeArray[val_one].sub.length
if(val[0]>=length){
   
   
   
  val=[length-1]
}else if(val[0]<0){
   
   
   
  val=[0]
}

之后我再回过头优化这个项目代码时发现这里(强制使用时将数组转为数字,反馈时将数字转为数组)其实大可不必:

JavaScript似乎对数据有自己“独特”的处理方式,但是目前笔者还没找到相关资料~~


如何判断一个值能不能作为数组下标(索引)

但是可以肯定的是:为整数属性键赋值是数组才有的特例,因为它们与非整数键的处理方式不同。要判断一个属性是否能作为数组的索引,笔者找到了ES6规范文档中的一段话:

这个操作用JS可以这样实现:

function toUint32(value){
   
   
   
    return Math.floor(Math.abs(Number(value))) % Math.pow(2,32);
}
function isArrayIndex(key){
   
   
   
    let numericKey=toUint32(key);
    return String(numericKey) == key && numericKey < (Math.pow(2,32)-1);
}
  1. toUint32() 函数通过规范中描述的算法将给定的值转换为无符号32位整数;
  2. isArrayIndex() 函数中先将键转换为uint32结构,然后进行两次比较(toString()后等不等于原数并且是否小于 2^32-1

有了这个基础,我们就可以基于此去简单模仿一下 new Array() 的行为 —— 其中最重要的还是关于length的描述:

function createArray(length=0){
   
   
   
    return new Proxy({
   
   
    length },{
   
   
   
        set(trapTarget,key,value){
   
   
   
            let currentLength=Reflect.get(trapTarget,"length");
            if(isArrayIndex(key)){
   
   
   
                let numericKey=Number(key);
                if(numericKey >= currentLength){
   
   
   
                    Reflect.set(trapTarget,"length",numericKey+1);
                }
            }else if(key === "length"){
   
   
   
                if(value < currentLength){
   
   
   
                    for(let index=currentLength-1;index >= value;index--){
   
   
   
                        Reflect.deleteProperty(trapTarget,index);
                    }
                }
            }
            // 无论key是什么类型都要执行这段代码
            return Reflect.set(trapTarget,key,value);
        }
    });
}

实验一下:

本文同步分享在 博客“行舟客”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

k
kazu7
世界是无情的,并不存在与生俱来的英雄。 所以只能由刚好在旁边的人粉墨登场, 演一出英雄的戏码。
3
发布数
3
关注者
15309
累计阅读

热门教程文档

Golang
23小节
Docker
62小节
Rust
84小节
Maven
5小节
C
14小节
广告