JavaScript

时间:2015-10-07 18:34:50

标签: javascript object properties identifier accessor

更新问题

究竟什么是Javascript中有效的属性名称?各种财产分配方法有何不同?属性名称如何影响属性访问?

注意

我原来的问题(见下文)的答案有助于澄清一些事情,但也开启了一堆新的蠕虫。现在我已经有机会对JavaScript变得更熟悉了,我相信我已经能够解决很多问题。

由于我很难将这些信息整合到一个解释中,我认为扩展原始问题可能会有所帮助,并试图回答它。

原始问题

最初,与MDN JavaScript guide (object literals)存在一些混淆。具体来说,我想知道为什么他们声称如果属性名称不是有效的JavaScript标识符,那么它必须用引号括起来。然而,他们提供了示例代码,表明可以使用数字7 - 没有引号 - 作为属性名称。

事实证明,该指南只是遗漏了一个重要部分,Pointy更新了它(粗体更改):

  

如果属性名称不是有效的JavaScript标识符或数字,则必须将其括在引号中。

我也想知道为什么允许属性名称偏离"可能不会以数字开头#34;规则,适用于标识符。这个问题实际上揭示了我对属性名称的完全误解,并且是导致我做更多研究的原因。

2 个答案:

答案 0 :(得分:2)

回答第一个问题:

是的,MDN指南中的陈述并非100%准确,但在日常工作中,最好遵守规则。您真的不需要创建数字属性名称。

回答第二个问题:

  

属性名称不能以数字开头,但属性名称可以是名称中没有任何其他字符的数字。

此异常的存在是因为名称编号的属性与indexes相同。

让我们试试这个:

var obj = {7: "abc"};
obj[7]; // works fine
obj.7; // gives an error (SyntaxError)

现在尝试在对象上调用Array.push并观察会发生什么:

Array.prototype.push.call(obj, "xyz");
console.log(obj);
console.log(obj[0]);

// Prints
Object {0: "xyz", 7: "abc", length: 1}
"xyz"

您可以看到几个新属性(一个名称为0,另一个名称为length)已添加到对象中。此外,您可以将对象用作数组:

var obj = { "0": "abc", "1": "xyz", length: 2 };

Array.prototype.pop.call(obj); // Returns: "xyz"
Array.prototype.pop.call(obj); // Returns: "abc"

您可以在对象上使用数组方法,这称为Duck Typing

数组只不过是带有一些预定义方法的对象。

来自MDN

  

数组元素是对象属性,其方式与length属性相同,但尝试使用点表示法访问数组元素会引发语法错误,因为属性名称无效。 JavaScript数组和导致此问题的属性没有什么特别之处。以数字开头的JavaScript属性不能用点表示法引用,必须使用括号表示法访问。

现在您可以理解为什么属性名称的数字有效。这些只是索引,它们用在JavaScript数组中。由于JavaScript需要与其他语言保持一致,因此数字对索引/属性名称有效。

希望这说清楚。

以下是一些有趣的文章:

答案 1 :(得分:1)

简答

对象属性名称可以是任意valid identifiernumeric literalstring literal(包括空字符串)。

话虽如此,但有一些可能令人困惑的错综复杂要记住JavaScript属性名称(摘要如下,explored more on my own)。

负数

看起来像负数的实际上是一个表达式 - 属性名称不支持。

$(function () {
var $win = $(window);

$win.scroll(function () {
    if ($win.scrollTop() == 0) {
        console.log("USER SCROLLED TO TOP");
        mixpanel.track(
            "User Scrolled To Top", {
            "url": window.location.href
        });
    } else if ($win.height() + $win.scrollTop() >= $('#below-fold').height() - 0 && $win.height() + $win.scrollTop() <= $('#below-fold').height() + 0) {
        console.log("VIEWED BELOW THE FOLD");
        mixpanel.track(
            "User Scrolled Below Fold", {
            "url": window.location.href
        });
    } else if ($win.height() + $win.scrollTop() == $(document).height()) {
        console.log("USER SCROLLED TO BOTTOM");
        mixpanel.track(
            "User Scrolled To Bottom", {
            "url": window.location.href
        });
    }
});

});

幸运的是,括号表示法为我们处理表达式。

var obj = {
  -12: 'nope' // I am an invalid property name, because I am an expression.
};

解析&amp;类型转换

在存储之前,所有属性名称都被转换为字符串。

obj[-6] = 'yup'; // Successful property assignment. We're good here.

但即使在此之前,它们也会根据使用的语法进行解析,并转换为十进制文字。

var obj = {
  lego: 'Everything is cool when you\'re part of a string.'
};

for (var key in obj) console.log(key); // "lego"

结论

除非您使用有效的(non-negative integer)数组索引,否则请将所有数字属性名称显式指定为字符串。