【发布时间】:2018-03-18 17:11:09
【问题描述】:
我有这条拼接线,两边各有一条调试线:
const obj = { x:[1,2], y:{t:"!!!"} }
const lenBefore = S.groupings.length
const ret = S.groupings.splice(gix, 0, obj)
console.log(`${lenBefore} --> ${S.groupings.length}, gix=${gix}, ret=${JSON.stringify(ret)}`)
它给出了这个输出,我认为这是不可能的:
3 --> 3, gix=2, ret=[]
即splice 没有添加或删除任何内容。
另一次运行,在不同的数据上,给出了:
18 --> 18, gix=2, ret=[]
这个函数相当复杂,但我有一些单元测试来涵盖它的主要使用方式。我在运行它们时留下了console.log() 行,这些测试给了我:
1 --> 2, gix=0, ret=[]
3 --> 4, gix=1, ret=[]
即正是我所期望的。因此,实际运行时环境的某些因素导致了这种情况。
(这是一个电子应用程序,这段代码在前端部分运行,即在Chrome中有效,我正在查看控制台是Chrome开发人员工具。单元测试在mocha 3.2中运行.0,节点6.11.4。真实环境是Electron 1.8.1,也就是Chrome 59,也就是稍微新一点。)
有谁知道什么外部环境可能导致splice() 无法完成其工作?
更新:
如果我改为使用它,那么在实时代码和单元测试中一切正常:
S.groupings = S.groupings.slice(0,gix).concat(obj, S.groupings.slice(gix))
S.groupings 显然有一些东西可以阻止它发生变异,但只是在我复杂的实时代码中,而不是在单元测试中!这本身就很有趣,因为我认为不可能制作不可变的 javascript 对象...
顺便说一句,以下代码:
console.log(`S type=${typeof S}; isArray=`+ Array.isArray(S))
console.log(`S.groupings type=${typeof S.groupings}; isArray=`+ Array.isArray(S.groupings))
在实时和单元测试代码中告诉我相同的结果:
S type=object; isArray=false
S.groupings type=object; isArray=true
我也试过这个,靠近函数的顶部:
S.groupings = Array.from(S.groupings)
没有区别。 IE。所有的证据都表明S.groupings 只是一个普通的 JavaScript 数组。
更新 2:未冷冻或密封:
Object.isFrozen(S.groupings) //false
Object.isSealed(S.groupings) //false
Object.isExtensible(S.groupings) //true
顺便说一句,为了缩小范围,我对真实代码进行了以下三个越来越复杂的简化,作为 mocha 测试。他们都完美地通过了。他们当然会。我决定将它包含在这里,因为它比我在上面发布的那一行提供了更多的上下文,并且还显示了一些显然 不是 解释的内容。
it("1", function(){
const S = {
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}
const obj = {a:2.5, b:"INSERT ME"}
let gix = 2
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
})
//--------------------------------
it("2", function(){
const S = {
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}
const CG = [ {z:1}, {z:2}, {z:3} ]
const obj = {a:2.5, b:"INSERT ME"}
for(let gix = 0;gix < CG.length; ++gix){
const g = CG[gix]
if(g.z < obj.a)continue
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
break
}
})
//--------------------------------
it("3", function(){
const data = {
"1":{},
"2":{
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}}
const CG_outer = [ {z:1}, {z:2}, {z:3} ]
function inner(CG, txt){
const S = data["2"]
const obj = {a:2.5, b:txt}
for(let gix = 0;gix < CG.length; ++gix){
const g = CG[gix]
if(g.z < obj.a)continue
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
break
}
}
inner(CG_outer, "INSERT ME")
assert.deepEqual(data["2"].groupings,
[ {a:1,b:2}, {a:2,b:"xxx"}, {a:2.5, b:"INSERT ME"}, {a:3,b:false} ] )
})
【问题讨论】:
-
S.groupings = Object.freeze([…])? -
@Bergi 猜得好——我认为这可能会导致这些症状。但我刚刚更新了我的问题以表明它没有被冻结。我确实(有点)弄清楚发生了什么,看看我的自我回答。
-
实际上我认为冻结的对象会引发异常。它必须是一个数组,其
length属性被覆盖不改变。
标签: javascript arrays google-chrome ecmascript-6 electron