我有这个拼接线,左侧有一个调试线:
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对象......
BTW,以下代码:
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)
没有任何区别。即所有证据都指出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} ] )
})
答案 0 :(得分:0)
我终于找到了它。电子应用程序具有独特的后端/前端进程,并具有消息解析功能。我这样做了:
S = mainProcess.getLatestData(...)
如果我改为:
const ret = mainProcess.getLatestData(...)
Object.assign(S, ret)
然后包括splice()
在内的所有内容都按预期工作。
ret
未被冻结,密封且可扩展。它似乎在所有方面都是一个普通的JS对象,ret.groupings
是一个简单的JS数组。
S
最初是来自前端的数据。 (但是这是从前端发送的,而不是请求的,这是电子中的两种不同的机制。)