javascript - 变量没有符号的语言如何处理动态调度/调用?

标签 javascript python ruby dynamic-languages sigils

动态语言允许使用仅在运行时才知道的变量的值进行分派(dispatch)和调用。 Perl 中的对比示例:

  1. 类名

    • 常量

      Foo::Bar->some_method
      Foo::Bar::->some_method
      'Foo::Bar'->some_method
      

    这些都是相同的,除了第一个是边缘情况。如果在范围内定义了一个具有该名称的子例程,则分派(dispatch)会在其返回值上发生,这会导致难以理解的错误。引用的版本始终是安全的。

    • 动态

      my $class_name = 'Foo::Bar';
      $class_name->some_method
      
  2. 方法名

    • 常量

      Some::Class->foo_bar
      
    • 动态

      my $method_name = 'foo_bar';
      Some::Class->$method_name
      
  3. 函数名

    • 常量

      foo_bar;
      (\&foo_bar)->()
      
    • 动态

      my $function_name = 'foo_bar';
      (\&$function_name)->()
      

我想知道,变量名没有符号(通常或根本没有)的语言是如何处理这些问题的,特别是它们的语言设计者是如何消除以下歧义的?

  1. 解析类名 FooBar.some_method 其中类 FooBar 可能是名称文字或值为类名的变量
  2. 调度到 SomeClass.foo_bar,其中方法 foo_bar 可能是名称文字或值为方法名称的变量
  3. 调用 foo_bar,其中函数可能是名称文字或值为函数的变量

我主要对这个问题的标签中提到的三种语言感兴趣,但如果你知道另一种没有印记的动态语言,你也可以回答。

最佳答案

在 python 和 js 中(我的 ruby​​ 有点生疏了)不可能在名称上下文中使用字符串。如果您尝试这样做,那将被解释为对字符串本身的操作:

class_name = 'Foo'
object = class_name()

> TypeError: 'str' object is not callable

应该首先通过在上下文/范围字典中查找来解析字符串:

class Foo:
   ....

object = globals()['Foo']()

function Foo() ....

object = new window['Foo'];

Python 提供全局和局部字典,js 只提供全局字典,所以除了无处不在的“eval”之外,没有办法从它的名称中获取局部值。

这同样适用于方法:您使用 getattr (python) 或间接引用运算符 [...] (js) 查找方法:

method_name = 'foo'
method = getattr(some_object, method_name)
method()

Javascript 代码稍微复杂一些,因为与 python 不同,返回的方法指针是未绑定(bind)的:

method_name = 'foo'
method = some_object[method_name].bind(some_object)
method()

如果没有 bind,您将无法在方法中获得正确的 this:

var obj = {
  
  xyz: 42,
  
  method: function() {
     document.write(this.xyz)
  }

}

var method_name = 'method';

var unbound_method = obj[method_name];
unbound_method() // prints undefined

var bound_method = obj[method_name].bind(obj);
bound_method() // prints 42

更正式地说,python/js中的点运算符.(相当于php的::->)需要一个右侧的标识符,并允许左侧的任意表达式。由于一切都是对象,如果左边的表达式返回一个字符串,则点适用于该字符串,而不适用于名称恰好等于该字符串的变量。

(附带说明,在点的右侧也允许表达式在技术上是可行的,这样 foo.('bar' + 'baz') 将解析为foo.barbaz。我不知道支持这种语法的语言,但它看起来是 getattr 和类似方法的不错替代品)。

类似地,调用运算符 () 允许在左侧使用复杂的表达式,此外,该表达式必须解析为“可调用”对象。因此,"someString"() 没有意义,因为字符串通常是不可调用的(除非您以某种方式破解它们,使它们可以调用)。

也就是说,如果你有一个包含变量名的字符串,你必须在使用前显式解析它。在幕后为您执行此操作的语言没有任何魔力。

关于javascript - 变量没有符号的语言如何处理动态调度/调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26402047/

相关文章:

ruby - 在 Ruby 中使用 return 不是惯用的吗?

javascript - CKEditor - 可以有基本样式的上下文菜单吗?

javascript - 比较两个数组并在 JS 中添加缺失的对象

python - 两个变量大小相同的散点图_实现难度

java - Java 中 RUBY 的等价物 has_many 和 belongs_to 关系

Ruby 文档丢失的东西

javascript - angularjs modal - 关闭后保留更改

javascript - 当 Breeze 导航属性受权限控制时访问它们

python - 狮身人面像自动模块 : how to reference classes in same module?

python - 如何在不同的子图中绘制 pcolor colorbar - matplotlib