很抱歉,我不能非常具体地说明脚本发生了什么。
我写了这段脚本来理解javascripit中的属性修改。我有一个变量ctx
,它有两个属性ctx.exports
和ctx.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.exports
与ctx.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");
}
答案 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.exports
到ctx.module.exports
的“链接”,因为对象本身不会重复,只会将其引用分配给ctx.module.exports
。
但在分配
之后ctx.exports = {
h: "hello"
}
链接的一部分被覆盖。
如果您想在不破坏链接的情况下向sys.exports
添加新值,可以使用以下命令:
ctx.exports.h = "hello";