为什么我们可以在Javascript函数声明中使用未定义的对象?

时间:2015-06-16 04:40:18

标签: javascript function

Chromium WebUI有一个cr.js文件,提供cr.define( name, fun )方法,用于模块化。 fun返回的对象的所有属性都将添加到name namescope对象中。

在Chrome浏览器书签管理器页面(chrome:// bookmarks)中,加载了一个名为bmm.js的Javascript源文件。 这是书签管理器中的Javascript模块。

以下是bmm.js文件的一部分,使用cr.define()定义了很多方法,然后将它们添加到bmm对象。

cr.define('bmm', function() {
  'use strict';

  function contains(parent, descendant) {
    if (descendant.parentId == parent.id)
      return true;
    // the bmm.treeLookup contains all folders
    var parentTreeItem = bmm.treeLookup[descendant.parentId];
    if (!parentTreeItem || !parentTreeItem.bookmarkNode)
      return false;
    return this.contains(parent, parentTreeItem.bookmarkNode);
  }

  // ... more function definitions ...

  return {
    contains: contains,
    isFolder: isFolder,
    loadSubtree: loadSubtree,
    loadTree: loadTree,
    addBookmarkModelListeners: addBookmarkModelListeners
  };
});

cr.define();的第二个参数是一个匿名函数表达式,它被解析并执行,返回的值是一个对象,然后作为参数传递给cr.define()

注意function contains()的函数声明中,使用bmm对象,在解析此函数体时应该是未定义的。

为什么我们可以在定义之前使用bmm及其方法treeLookup

contains()的函数体是否被解析并保存为语法树,其中许多节点是tokens = undefined?

无法解析并保存在原始源代码中,因为这意味着它根本不会被解析。

1 个答案:

答案 0 :(得分:3)

  

cr.define()的第二个参数是一个匿名函数表达式,它被解析并执行,返回的值是一个对象,然后作为参数传递给cr.define()

事实上并非如此。它只是作为函数传递给cr.define而没有被调用。它是从within there执行的:

var exports = fun();
  

注意function contains()的函数声明中,使用bmm对象,在解析此函数体时应该是未定义的。

是。这根本不重要。它只是一个名为bmm的自由变量。

仅在调用函数时才会解析。

  

为什么我们可以在定义之前使用bmm及其方法treeLookup

未使用它们 - contains未被调用。它们只是解析时的标识符。只有在实际执行代码时才会动态调度方法调用。

  

contains()的函数体是否已解析并保存为语法树?

是。这就是解析的作用。

  

其中许多节点是tokens = undefined?

没有。语法树不存储值。存储它们的记录是在运行时创建的,值本身也是如此。只有这样才能进行分配和查找。