javascript - 在 reducer 函数中更改 targetArray.length 时的 targetArray.reduce 行为
问题描述
这个问题主要针对那些使用 ECMAScript 规范和/或实现它的人。
规范Array.prototype.reduce(callbackfn[,initialValue])
指定了算法。看到算法,第 2 步,读取Let len be ? ToLength(? Get(O, "length"))
之后,我的理解是len
永远不会再更新。但是,看看这个:
const a = [0,1,2,3,4];
a.reduce(p=>{
a.splice(0,1);
console.log(a);
return p;
},a);
// Logs:
// [1,2,3,4]
// [2,3,4]
// [3,4]
// and that's it
由于迭代应该运行while k<len
(k
作为迭代计数器),这种行为表明,在我尝试的实现(Chrome、Edge、Node)中,len
每次迭代都会更新到a
当前迭代的长度。
这真的是预期的行为吗?是否有具体的原因为什么len
在每次迭代时故意更新,而不是像规范中指定的那样从一开始就保持固定?
解决方案
您看到的行为是由于步骤 9.2:仅当对象上存在属性时才调用回调。它确实迭代了 5 次,但是在您删除 3 个元素之后,在第四次和第五次迭代a.hasOwnProperty(3)
中a.hasOwnProperty(4)
是错误的。
我们可以用代理来最好地证明这一点:
const a = [0,1,2,3,4];
new Proxy(a, {
has(target, p) { const v = Reflect.has(target, p); console.log("has", p, v); return v },
get(target, p) { const v = Reflect.get(target, p); console.log("get", p, v); return v }
}).reduce((p, e) => {
a.length--;
console.log("at " + e, a);
return p;
}, null);
或者通过调用reduce
其.length
更改不影响属性的对象:
const a ={0:0,1:1,2:2,3:3,4:4,length:5,reduce:Array.prototype.reduce};
a.reduce((p, e) => {
a.length--;
console.log("at " + e, a);
return p;
}, null);
推荐阅读
- kubernetes - 尝试在版本 networking.internal.knative.dev/v1alpha1 中创建一种集群域声明时出现错误
- react-native - 如何添加圆来反应原生进度条
- mapbox - Android v10 SDK 中的 onCameraIdleListener 等效项
- android-studio - 根本无法查看项目
- c - 如何在 c 程序中使用 getrlimit 获取普通用户的 nproc
- spring - 为什么我的 Spring Boot 应用程序即使在配置之后也不启动执行器
- node.js - 覆盆子通过 /etc/profile 和桌面自动启动执行节点 js 脚本
- laravel - 分离的 [create] 和 [store] 函数的验证在 Laravel6 中不起作用
- python - 如何向现有 df 添加多级列索引?
- amazon-web-services - AWS Cognito:无法使用 aws cli 为 create-user-pool 设置一些属性