这个脚本是怎么回事

whats going on in this script

很抱歉,我不能非常具体地说明脚本发生了什么。 我写这段脚本是为了理解 java 脚本中的 属性 修改。我有一个变量 ctx,它有两个属性 ctx.exportsctx.module.exports。正如您在下面看到的 int eh 代码,我已经建立了关系 ctx.module.exports = ctx.exports 所以当 ctx.exports 被修改时 ctx.module.exports 保持相同的值。 但下面的脚本另有建议。

var ctx = {};
ctx.exports = {};
ctx.module = {
  exports: ctx.exports
}

ctx.exports = {
  h: "hello"
}


if (ctx.exports == ctx.module.exports) {
  console.log("hi");
} else {
  console.log("hey");
}

然而,在这种情况下,当我将 ctx.exports 值存储到局部变量 exports 时。 exports 在修改 ctx.exports

时与 ctx.module.exports 相等

var ctx = {};
ctx.exports = {};
ctx.module = {
  exports: ctx.exports
}

var exports = ctx.exports;
ctx.exports = {
  h: "hello"
}


if (exports == ctx.module.exports) {
  console.log("hi");
} else {
  console.log("hey");
}

cn 谁能给我解释一下这种情况是怎么回事?这是 java 脚本中的一种范围界定吗?这个有专有名称吗?

编辑

正如第一个答案所解释的那样,ctx.module.exports 正在检查 {} 这就是它匹配的原因。但在那种情况下,为什么会失败

var ctx = {};
ctx.exports = {};
ctx.module = {
  exports: ctx.exports
}

var exports = ctx.exports;
ctx.exports = {
  h: "hello"
}

if ({} == ctx.module.exports) {
  console.log("hi");
} else {
  console.log("hey");
}

看看比较的是什么。在第一个示例中,您将 ctx.module.exports 设置为引用 ctx.exports,这是一个空对象:{}。然后你用新值覆盖 ctx.exports{ h: "hello" }ctx.module.exports 保留了对原始对象的引用,而 ctx.exports 现在引用了一个不同的对象:您正在将 {}{ h: "hello" }.

进行比较

在第二个示例中,您再次用新对象覆盖 ctx.exports,但您正在比较对原始对象的两个引用:{}{}。是一场比赛。

编辑 - 为了更清楚一点 设置变量的值时,您将名称链接到引用。覆盖该变量会创建一个同名的新引用,但不会修改该引用,这就是覆盖 ctx.exports 对其他任何一个引用都没有影响的原因。

编辑对问题的回复编辑 你不能这样比较对象。 {} !== {} 因为每个对象字面量声明都会创建一个新的 Object 实例。可以比较您的引用的原因是因为它们是对同一对象的引用,即由 ctx.exports = {}.

创建的对象

更多编辑! 通过比较每个对象的 JSON 值,您可以看到效果:JSON.stringify({}) == JSON.stringify(ctx.module.exports) 为真,因为它比较的是相同的字符串; {} == ctx.module.exports 是假的,因为它比较的是不同的对象,尽管两个对象在构造上是相同的。

我认为你的问题不在于比较,而在于赋值:

ctx.module = {
  exports: ctx.exports
}

这会创建一个 ctx.exportsctx.module.exports 的 "link",因为对象本身没有被复制,而只是它被分配给 ctx.module.exports 的引用。

但是赋值后

ctx.exports = {
  h: "hello"
}

link 的一部分被覆盖。

如果你想在不破坏 link 的情况下向 sys.exports 添加一个新值,你可以使用这个:

ctx.exports.h = "hello";