【问题标题】:Call methods on native Javascript types without wrapping with ()在不使用 () 包装的情况下调用本机 Javascript 类型的方法
【发布时间】:2011-02-13 04:06:57
【问题描述】:

在 Javascript 中,我们可以直接调用字符串字面量的方法,而无需将其括在圆括号内。但不适用于其他类型,例如数字或函​​数。这是一个语法错误,但是否有理由说明为什么 Javascript 词法分析器需要将这些其他类型括在圆括号中?

例如,如果我们使用 alert 方法扩展 Number、String 和 Function,并尝试在字面量上调用此方法,则它对于 Number 和 Function 来说是 SyntaxError,而对于 String 有效。

function alertValue() {
    alert(this);
}

Number.prototype.alert = alertValue;
String.prototype.alert = alertValue;
Function.prototype.alert = alertValue;

我们可以直接在字符串对象上调用alert:

"someStringLiteral".alert() // alerts someStringLiteral

但这是数字和函数的语法错误。

7.alert();
function() {}.alert();

要使用这些类型,我们必须将其括在括号中:

(7).alert(); // alerts "7"
(function() {}).alert(); // alerts "function() {}"

更新

@Crescent 的链接以及@Dav 和@Timothy 的回答解释了为什么7.alert() 会失败,因为它正在寻找一个数字常量,并且要通过它,插入额外的空格或额外的点。

7 .alert()
7..alert()
7. .alert();

在对函数调用方法之前,为什么需要将函数括在括号中,是否存在类似的语法原因?

我不熟悉解释器和词法分析器,不知道这是否是一个可以通过某种前瞻来解决的问题,因为 Ruby 是一种动态语言并且可以解决这个问题。例如:-

7.times { |i| print i }

更新 2

@CMS 的答案在理解为什么上面的函数不起作用。以下语句有效:

// comma operator forces evaluation of the function
// alerts "function() {}"
<any literal>, function() {}.alert();​​​​​​​

// all examples below are forced to be evaluated as an assignment expression
var a = function() {}.alert(); 

var b = {
    x: function() { return "property value" }.alert()
}

[ function() { return "array element" }.alert() ];​

【问题讨论】:

  • “圆括号”被称为圆括号...
  • 感谢@Crescent 的链接,它解释了数字,函数有类似的原因吗?
  • 另外,不要像这个回答者那样思考:stackoverflow.com/questions/203739/…(需要更多反对票)。
  • @Jimmy,我在发布问题时努力记住“parantheses”,但就是想不起来:)。圆括号,虽然有点冗长也很常见。

标签: javascript syntax methods lexer


【解决方案1】:

提示:7. 是一个有效的数字常量。

【讨论】:

    【解决方案2】:

    当词法分析器看到一个数字紧跟一个句点时,它需要一个十进制值。尽管您可以“有创意”并在数字之间放置一个空格,例如 7 .alert(),但是当人们在维护您的代码时遇到困难时,他们可能会追捕您!

    【讨论】:

    • 7 .alert()7..alert() 是解决这个问题的聪明方法(尽管当事情确实发生时对于维护程序员来说是噩梦),但我想知道这是否可以解决在解析标记时在词法分析器端,并在构建语法树时进行某种前瞻。 Ruby 是一种动态语言,使用类似的语法,例如)5.times { |i| print i }
    【解决方案3】:

    在数字期望的地方使用小数点,点运算符将按照对象的期望工作。

    7.0.toFixed(0)

    【讨论】:

      【解决方案4】:

      对于Number 文字,所有其他答案都为您指明了正确的方向,7. 是有效的DecimalLiteral

      grammar 告诉您第一个点之后的十进制数字是可选的:

      DecimalLiteral ::
      DecimalIntegerLiteral . DecimalDigitsopt ExponentPartopt 
      

      * 注意 opt 后缀

      现在,对于函数,问题在于它正在语句上下文中进行评估。

      创建函数对象有两种有效的语法方法(第三种创建函数的方法是使用Function constructor,但目前不在主题范围内)。

      函数声明:

      function name(/*[param] [, param] [..., param]*/) {
         // statements
      }
      

      函数表达式:

      var foo = function /*nameopt*/(/*[param] [, param] [..., param]*/) {
        // statements
      };
      

      语法几乎相同,不同之处在于function关键字出现的位置。

      function 关键字直接在全局代码或函数的FunctionBody 中找到时,就会出现function declaration

      出现function expression,然后在表达式上下文中找到function关键字,就像上面的例子一样,第二个函数是AssignmentExpression的一部分。

      但你实际上有两个问题,第一,FunctionDeclaration 的名称是强制性的。

      其次,在评估 FunctionDeclaration 语句时,点将简单地导致 SyntaxError,因为点不是预期的。

      用括号括起函数(正式名称为The Grouping Operator)使函数在表达式上下文中被评估,function expression

      例如,以下是有效的:

      0,function () {}.alert();
      

      上述方法有效,因为comma operator 评估表达式

      您还应该知道FunctionDeclarations 在“解析时”(更准确地说,当控件进入Execution Context 时,由Variable Instantiation 进程进行评估),并生成标识符(函数名称)可用于整个当前范围,例如:

      foo(); // alerts "foo", function made available at 'parse time'
      foo = function () { alert('bar') }; // override with a FunctionExpression
      function foo () { alert('foo'); } // FunctionDeclaration
      foo(); // alerts "bar", the overriden function
      

      推荐文章:

      【讨论】:

      • 非常感谢这个详细的答案。它对提高我对 Javascript 的理解很有帮助。
      • 不客气@Anurag,如果您有任何疑问,请发表评论。
      【解决方案5】:

      我更喜欢用括号来消除歧义:

      (7).alert();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-07
        相关资源
        最近更新 更多