什么外部环境可能导致拼接无法做任何事情?

时间:2017-10-06 20:25:20

标签: javascript arrays google-chrome ecmascript-6 electron

我有这个拼接线,左侧有一个调试线:

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} ] )
})

1 个答案:

答案 0 :(得分:0)

我终于找到了它。电子应用程序具有独特的后端/前端进程,并具有消息解析功能。我这样做了:

S = mainProcess.getLatestData(...)

如果我改为:

const ret = mainProcess.getLatestData(...)
Object.assign(S, ret)

然后包括splice()在内的所有内容都按预期工作。

但是,我无法解释发生了什么。 ret未被冻结,密封且可扩展。它似乎在所有方面都是一个普通的JS对象,ret.groupings是一个简单的JS数组。

S最初是来自前端的数据。 (但是这是从前端发送的,而不是请求的,这是电子中的两种不同的机制。)