你在这个剧本中发生了什么

时间:2017-01-19 21:46:36

标签: javascript properties scope scoping

很抱歉,我不能非常具体地说明脚本发生了什么。 我写了这段脚本来理解javascripit中的属性修改。我有一个变量ctx,它有两个属性ctx.exportsctx.module.exports。正如您在下面的代码中看到的,我建立了关系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.module.exportsctx.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");
}

2 个答案:

答案 0 :(得分:1)

看看正在比较的内容。在第一个示例中,您将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是错误的,因为它正在比较不同的对象,尽管两个对象建设性地相同。

答案 1 :(得分:1)

我认为你的问题不在于比较,而在于作业:

ctx.module = {
  exports: ctx.exports
}

这会创建ctx.exportsctx.module.exports的“链接”,因为对象本身不会重复,只会将其引用分配给ctx.module.exports

但在分配

之后
ctx.exports = {
  h: "hello"
}

链接的一部分被覆盖。

如果您想在不破坏链接的情况下向sys.exports添加新值,可以使用以下命令:

ctx.exports.h = "hello";