与Java不同,Javascript中的赋值运算符是否意味着LHS上的所有操作都会反映在RHS上?

与Java不同,Javascript中的赋值运算符是否意味着LHS上的所有操作都会反映在RHS上?,javascript,Javascript,这是问题“”的答案的继续 代码就像一个符咒,但我无法理解它是如何工作的!!所以几天后+我的console.log实际上超过了我的代码行的情况:P。。我的问题是: 下面是JavaScript函数的代码: 功能深化(o){ var oo={},t,parts,part; for(变量k in o){ t=oo; 部分=k.分割('.'); var key=parts.pop(); while(零件长度){ part=parts.shift(); t=t[part]=t[part]|{}; } t[

这是问题“”的答案的继续

代码就像一个符咒,但我无法理解它是如何工作的!!所以几天后+我的console.log实际上超过了我的代码行的情况:P。。我的问题是:

下面是JavaScript函数的代码:

功能深化(o){
var oo={},t,parts,part;
for(变量k in o){
t=oo;
部分=k.分割('.');
var key=parts.pop();
while(零件长度){
part=parts.shift();
t=t[part]=t[part]|{};
}
t[key]=o[k]
}
返回oo;
}
console.log(
加深({'ab.cd.e':'foo','ab.cd.f':'bar','ab.g':'foo2'})

);首先,您使用的不是JSON,而是JS对象。大多数情况下,如果需要Java类比,您应该将对象视为无限的
HashMap

你的问题:

  • t=oo
    表示它们都引用在函数开始时创建的同一实例。为什么要使用第二个变量
  • t=t[part]
    您可以直接将
    t
    的条目分配给
    t
  • 我没有测试代码,但我很确定它有缺陷。测试顶级中有多个名称的对象会发生什么情况,例如,
    {'a.b':1,'b.a':1}
    。不过,您不需要递归,可以使用堆栈
  • 关于您的代码:

  • 使用描述性的名称和注释,尤其是在询问其他人需要理解您的代码的问题时
  • 不要在函数开头定义所有变量。这种老习惯源于C语言的早期,需要改掉
  • for(var k in o)
    不是迭代对象条目的推荐方法。使用
  • 不需要从部件数组弹出,每次迭代都会重置它<代码>for(const part of parts)
  • 也可以
    我将首先用一些更好的名称重新定义函数,这样解释就容易多了

    function deepen(object) {
      var nestedObject = {}, cursor, nestingPath, nodeKey;
    
      for (var dotKey in object) {
        cursor = nestedObject;
        nestingPath = dotKey.split('.');
        var leafKey = nestingPath.pop();
    
        while (nestingPath.length) {
          nodeKey = nestingPath.shift();
          cursor = cursor[nodeKey] = cursor[nodeKey] || {};
        }
        cursor[leafKey] = object[dotKey];
      }
    
      return nestedObject;
    }
    

    我的猜测是,我并不完全知道while循环是如何工作的。重要的是要知道,当两个变量引用同一个对象时,当您更改一个对象时,两个变量都会更改。它们是相同的对象,但您选择了两个控制柄

    让我举一个例子:

    object = {};
    cursor = object;
    
    cursor.foo = "bar";
    
    object; //=> {foo: "bar"}
    cursor; //=> {foo: "bar"}
    
    cursor.a = {};
    
    object; //=> {foo: "bar", a: {}}
    cursor; //=> {foo: "bar", a: {}}
    
    cursor = cursor.a;
    
    object; //=> {foo: "bar", a: {}}
    cursor; //=> {}   <- this is ^
    
    cursor.b = "c";
    
    object; //=> {foo: "bar", a: {b: "c"}}
    cursor; //=> {b: "c"}
    
    这也可以写成:

    if (!cursor[nodeKey]) cursor[nodeKey] = {};
    cursor = cursor[nodeKey];
    

    如果动态
    nodeKey
    属性不存在(falsy),则会将新对象指定给该属性。然后将
    cursor
    指定给中的嵌套对象,类似于我上面的示例
    cursor=cursor。a

    讨论不是以模糊方式编写的代码要容易得多。具体地说,在需要变量时定义变量,并为它们指定描述性名称。如果你需要帮助,我们会在这里帮助你,但不要试图不必要地迷惑我们\这看起来是一个很好的问题——它包含了先前的研究、个人努力、使用降价的良好格式,并显示了代码。但是,请尽量避免在这里的帖子中给出投票建议-大多数用户都没有登录,因此这对他们没有用处,而且在任何情况下给出建议都会鼓励相反的行为!“这个旧习惯源于C语言的早期,需要改掉。”我同意它需要改掉,但Crockford不是也提倡它吗?他有一个合乎逻辑的理由——
    var
    s没有块作用域,所以你不应该在
    if
    for
    中“声明”一个,因为这会误导你认为它在外面是不可见的。因此,他的解决方案是将所有变量放在函数的顶部,以便明确其作用域。作为记录,我发现这比使用
    if(cond){var x=“whatever”}
    更糟糕。像Crockford的很多东西一样,它有意义,但没有用处。当使用
    var
    时,我仍然在函数顶部有所有变量定义。这样,范围就清晰了,因为
    var
    变量被提升。然而,随着
    let
    const
    的引入,我认为没有多少理由使用
    var
    。使用
    let
    const
    定义的变量未被提升,因此我在需要时定义它们。对于@3limin4t0r的延迟回复,我深表歉意。我没有收到通知,所以当我再次访问时,请通读线程。非常感谢。这确实有助于澄清我在理解它时存在的概念差距。我相信这段代码是一个树构造算法的实现?与Java相比,JS看起来是程序化的,您是否建议我重新审视数据结构,作为精通Javascript的必要条件?
    if (!cursor[nodeKey]) cursor[nodeKey] = {};
    cursor = cursor[nodeKey];