【问题标题】:JavaScript property access: dot notation vs. brackets?JavaScript 属性访问:点符号与括号?
【发布时间】:2017-02-05 21:36:09
【问题描述】:

除了第一种形式可以使用变量而不仅仅是字符串文字这一显而易见的事实之外,还有什么理由使用一个而不是另一个,如果是,在哪些情况下?

在代码中:

// Given:
var foo = {'bar': 'baz'};

// Then
var x = foo['bar'];

// vs. 
var x = foo.bar;

上下文:我编写了一个生成这些表达式的代码生成器,我想知道哪个更可取。

【问题讨论】:

标签: javascript syntax object-literal


【解决方案1】:

(来自here。)

方括号表示法允许使用点表示法不能使用的字符:

var foo = myForm.foo[]; // incorrect syntax
var foo = myForm["foo[]"]; // correct syntax

包括非 ASCII (UTF-8) 字符,如 myForm["ダ"] (more examples)。

其次,方括号符号在处理时很有用 以可预测方式变化的属性名称:

for (var i = 0; i < 10; i++) {
  someFunction(myForm["myControlNumber" + i]);
}

综述:

  • 点表示法书写速度更快,阅读更清晰。
  • 方括号表示法允许访问包含以下内容的属性 特殊字符和选择 使用变量的属性

另一个不能与点表示法一起使用的字符示例是本身包含点的属性名称

例如,一个 json 响应可能包含一个名为 bar.Baz 的属性。

var foo = myResponse.bar.Baz; // incorrect syntax
var foo = myResponse["bar.Baz"]; // correct syntax

【讨论】:

【解决方案2】:

括号表示法允许您通过存储在变量中的名称访问属性:

var obj = { "abc" : "hello" };
var x = "abc";
var y = obj[x];
console.log(y); //output - hello

obj.x 在这种情况下不起作用。

【讨论】:

    【解决方案3】:

    在 JavaScript 中访问属性的两种最常见的方法是使用点和方括号。 value.xvalue[x] 都访问值属性,但不一定是相同的属性。 不同之处在于 x 的解释方式。使用点时,点后面的部分必须是有效的变量名,直接命名属性。使用方括号时,对括号之间的表达式求值以获取属性名称。 value.x 获取名为“x”的值的属性,而 value[x] 尝试计算表达式 x 并将结果用作属性名称。

    所以如果你知道你感兴趣的属性叫做“长度”,你说value.length。如果要提取由变量i 中保存的值命名的属性,请说value[i]。并且因为属性名称可以是任何字符串,如果要访问名为 “2”“John Doe” 的属性,则必须使用方括号:value[2]value["John Doe"]。即使您事先知道属性的确切名称也是如此,因为“2”“John Doe” 都不是有效的变量名称,因此无法通过点符号访问。

    如果是数组

    数组中的元素存储在属性中。因为这些属性的名称是数字,我们经常需要从变量中获取它们的名称,所以我们必须使用括号语法来访问它们。 数组的长度属性告诉我们它包含多少元素。这个属性名是一个有效的变量名,我们事先知道它的名字,所以要找到一个数组的长度,你通常写array.length,因为这比array["length"]更容易写。

    【讨论】:

    • 您能否详细说明array.length?你说通过点符号访问的属性没有被评估,所以在 array.length 的情况下,它不会给我们“长度”字符串而不是评估值,在这种情况下是数组中的项目数? The elements in an array are stored in properties 这让我很困惑。存储在属性中是什么意思?什么是属性?在我的理解中,数组只是一堆没有属性的值。如果存储在属性中,怎么不是property: value/关联数组?
    • 这个答案特别有价值,因为它解释了两种符号之间的区别。
    【解决方案4】:

    点表示法不适用于 Internet Explorer 8 中的某些关键字(如 newclass)。

    我有这个代码:

    //app.users is a hash
    app.users.new = {
      // some code
    }
    

    这会触发可怕的“预期标识符”(至少在 windows xp 上的 IE8 上,我还没有尝试过其他环境)。解决这个问题的简单方法是切换到括号表示法:

    app.users['new'] = {
      // some code
    }
    

    【讨论】:

    【解决方案5】:

    一般来说,他们做同样的工作。
    尽管如此,括号符号让您有机会做点符号无法做到的事情,例如

    var x = elem["foo[]"]; // can't do elem.foo[];
    

    这可以扩展到任何包含特殊字符的属性。

    【讨论】:

      【解决方案6】:

      使用这些符号时要小心: 例如。如果我们想访问存在于窗口父级中的函数。 在 IE 中:

      window['parent']['func']
      

      不等于

      window.['parent.func']
      

      我们可以使用:

      window['parent']['func'] 
      

      window.parent.func 
      

      访问它

      【讨论】:

        【解决方案7】:

        如果属性名称有特殊字符,则需要使用括号:

        var foo = {
            "Hello, world!": true,
        }
        foo["Hello, world!"] = false;
        

        除此之外,我想这只是品味问题。恕我直言,点符号更短,它更明显地表明它是一个属性而不是数组元素(当然 JavaScript 无论如何都没有关联数组)。

        【讨论】:

          【解决方案8】:

          当 - 时你必须使用方括号表示法

          1. 属性名称是数字。

            var ob = {
              1: 'One',
              7 : 'Seven'
            }
            ob.7  // SyntaxError
            ob[7] // "Seven"
            
          2. 属性名称有特殊字符。

            var ob = {
              'This is one': 1,
              'This is seven': 7,
            }  
            ob.'This is one'  // SyntaxError
            ob['This is one'] // 1
            
          3. 属性名称已分配给变量,并且您要访问 此变量的属性值。

            var ob = {
              'One': 1,
              'Seven': 7,
            }
            
            var _Seven = 'Seven';
            ob._Seven  // undefined
            ob[_Seven] // 7
            

          【讨论】:

            【解决方案9】:

            foo.barfoo["bar"] 都访问 foo 上的属性,但不一定是相同的属性。区别在于bar 的解释方式。使用点时,点后面的单词是属性的字面名称。使用方括号时,对括号之间的表达式求值以获取属性名称。而foo.bar 获取 名为 “bar”foo["bar"] 的值的属性尝试计算表达式 "bar" 并使用转换为字符串的结果作为属性名称

            点表示法的局限性

            如果我们接受这个项目:

            const obj = {
              123: 'digit',
              123name: 'start with digit',
              name123: 'does not start with digit',
              $name: '$ sign',
              name-123: 'hyphen',
              NAME: 'upper case',
              name: 'lower case'
            };
            

            使用点符号访问它们的专有属性

            obj.123;      // ❌ SyntaxError
            obj.123name;  // ❌ SyntaxError
            obj.name123;  // ✅ 'does not start with digit'
            obj.$name;    // ✅  '$ sign'
            obj.name-123;  // ❌ SyntaxError
            obj.'name-123';// ❌ SyntaxError
            obj.NAME; // ✅ 'upper case'
            obj.name; // ✅ 'lower case'
            

            但是对于括号符号来说,这些都不是问题:

            obj['123'];     // ✅ 'digit'
            obj['123name']; // ✅ 'start with digit'
            obj['name123']; // ✅ 'does not start with digit'
            obj['$name'];   // ✅ '$ sign'
            obj['name-123']; // ✅ 'does not start with digit'
            obj['NAME']; // ✅ 'upper case'
            obj['name']; // ✅ 'lower case'
            

            使用变量访问变量:

            const variable = 'name';
            const obj = {
              name: 'value'
            };
            // Bracket Notation
            obj[variable]; // ✅ 'value'
            // Dot Notation
            obj.variable; // undefined
            

            【讨论】:

            • 因为求值,括号符号会不会慢一些?
            【解决方案10】:

            括号表示法可以使用变量,因此在点表示法不起作用的两种情况下很有用:

            1) 动态确定属性名称时(直到运行时才知道确切名称时)。

            2) 当使用 for..in 循环遍历对象的所有属性时。

            来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects

            【讨论】:

              【解决方案11】:

              [] 符号有用的情况:

              如果您的对象是动态的,并且键中可能有一些随机值,例如 number[] 或任何其他特殊字符,例如 -

              var a = { 1 : 3 };

              现在,如果您尝试像a.1 一样访问它,它会出现错误,因为它需要一个字符串。

              【讨论】:

                【解决方案12】:

                点符号总是更可取。如果您使用一些“更智能”的 IDE 或文本编辑器,它将显示该对象中未定义的名称。 仅当您的名称带有类似破折号或类似无效的名称时,才使用括号表示法。如果名称存储在变量中。

                【讨论】:

                • 而且在某些情况下,即使您没有破折号,也根本不允许使用括号表示法。例如,你可以写Math.sqrt(25),但不能写Math['sqrt'](25)
                【解决方案13】:

                让我添加更多方括号表示法的用例。如果你想访问对象中的属性比如x-proxy,那么- 将被错误地解释。它们还有其他一些情况,例如空格,点等,点操作对您没有帮助。此外,如果您在变量中有键,那么访问对象中键的值的唯一方法是通过括号表示法。希望您能获得更多背景信息。

                【讨论】:

                  【解决方案14】:

                  点符号失败的例子

                  json = { 
                     "value:":4,
                     'help"':2,
                     "hello'":32,
                     "data+":2,
                     "?":'?',
                     "a[]":[ 
                        2,
                        2
                     ]
                  };
                  
                  // correct
                  console.log(json['value:']);
                  console.log(json['help"']);
                  console.log(json["help\""]);
                  console.log(json['hello\'']);
                  console.log(json["hello'"]);
                  console.log(json["data+"]);
                  console.log(json["?"]);
                  console.log(json["a[]"]);
                  
                  // wrong
                  console.log(json.value:);
                  console.log(json.help");
                  console.log(json.hello');
                  console.log(json.data+);
                  console.log(json.?);
                  console.log(json.a[]);
                  
                  

                  属性名称不应干扰 javascript 的语法规则,以便您能够以 json.property_name 访问它们

                  【讨论】:

                    【解决方案15】:

                    或者当您想要动态更改元素的 classList 操作时:

                    // Correct
                    
                    showModal.forEach(node => {
                      node.addEventListener(
                        'click',
                        () => {
                          changeClass(findHidden, 'remove'); // Correct
                        },
                        true
                      );
                    });
                    
                    //correct
                    function changeClass(findHidden, className) {
                      for (let item of findHidden) {
                        console.log(item.classList[className]('hidden'));// Correct
                      }
                    }
                    
                    // Incorrect 
                    function changeClass(findHidden, className) {
                      for (let item of findHidden) {
                        console.log(item.classList.className('hidden')); // Doesn't work
                      }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      相关资源
                      最近更新 更多