0

我试图理解 CoffeeScript 生成的这段 JavaScript 代码。

我习惯于看到函数定义为:

  • function Animal(name) {...}
  • var Animal = function(name){...};

但是 CoffeeScript 会产生以下结果:

var Animal = (function() {
  function Animal(name) {
    this.name = name;
  }

  return Animal;

})();

问题:

  • 在匿名函数中创建“命名”函数有什么作用?
  • 像这样定义 Animal 函数与两种项目符号方式之一有什么优势?

奖金问题 这些是等价的吗?

//Methodology #1
function Animal(name) {...}
//Methodology #2
var Animal = function Animal(name) {...};
4

4 回答 4

1
  1. 在匿名函数中创建“命名”函数有什么作用?

    更新

    由于 JScript 错误,这仅适用于 IE8,在现代(和健全的)浏览器中,使用命名函数表达式时,Animal 未在上下文命名空间中注册。

    它防止函数声明在上下文(可能是全局命名空间)中注册函数名。这意味着如果你这样做:

    var Tiger = function Animal() {};
    

    两者都在全局命名空间TigerAnimal注册,而这个:

    var Tiger = function() { function Animal() {}; return Animal; };
    

    Animal在全局命名空间中注册。

  2. 像这样定义 Animal 函数与两种项目符号方式之一有什么优势?

    更新

    同样,如果适用于比 IE8 更现代的浏览器,这也是无效的。在这些情况下,您可以使用命名函数表达式而无需担心您的上下文。

    优点是在保持上下文(同样,可能是全局)命名空间干净的同时,您仍然可以为您的对象拥有一个命名构造函数。这意味着:

    var Tiger = function() {};
    var t = new Tiger();
    t.constructor // is an anonymous function() {}
    

    声明性低于

    var Tiger = function() { function Animal() {}; return Animal };
    var t = new Tiger();
    t.constructor // is a function Animal()
    Animal //=> is not defined
    

    这会污染全局名称空间或上下文名称空间,并可能不需要注册Animal

    var Tiger = function Animal() {};
    var t = new Tiger();
    t.constructor // is a function Animal()
    Animal //=> returns function Animal();
    
  3. 这些是等价的吗?

    更新

    这适用于所有浏览器。

    不。在第一个中,您以 的名称声明一个函数Animal,而在第二个中,您将一个以 的名称声明的函数分配给一个名为 的Animal变量Animal,这称为命名函数表达式。首先,查找通过函数名进行,其次,查找通过变量名进行。这是因为函数声明不能​​覆盖函数表达式:函数声明在脚本加载的上下文中加载,而表达式赋值是在脚本执行时执行的:

    function a() { 
      var b = function() { return 3; }; 
      return b(); 
      function b() { return 9; } 
    }
    
    a() //=> returns 3;
    
于 2013-04-22T16:19:24.560 回答
1

像这样定义 Animal 函数与两种项目符号方式之一有什么优势?

  1. 该函数仍将有一个显示在调试控制台中的名称
  2. 尽管有名称,但该函数不会污染全局命名空间,因为它的作用域对于匿名包含函数是本地的,并且它可以作为闭包使用。

关于你的奖金问题:

http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

于 2013-04-22T16:10:00.893 回答
0

您熟悉OOP(面向对象编程)吗?

因为在这里您看到的是尝试在 JavaScript 中定义对象,即使 JavaScript 中没有class关键字。

如果您对 Java 有一点了解(它与 JavaScript 几乎没有任何关系),那么这应该看起来很熟悉:

public class Animal { // creating a class
    private String name; // declaring its attributes

    public Animal(String name) { // declaring constructor
        this.name = name; // assigning value to the attribute
    }
}

您提供的 JavaScript 代码基本上做同样的事情,例如创建一个类(某种增强类型),它具有属性(分配给它的变量)和方法(分配给它的函数)。

所以这段代码

function Animal(name) {
    this.name = name;
}

创建Animal类。

问题是在 JavaScript 中,实际上并没有任何的概念,而只有对象的概念。因此,您在这里创建一个变量,然后分配以下函数的结果:

var Animal = (function() {
    // some code here
})
(); // note the parenthesis here that means the function is called

然后,定义一个构造函数,并返回包含该函数的对象。

所以在执行结束时,var Animal包含一个构造函数,因此任何对象都可以像这样初始化:̀var myAnimal = new Animal('Panther');.

希望有帮助。

于 2013-04-22T16:25:46.830 回答
0

“在匿名函数中创建“命名”函数有什么作用?”

它只是创建一个新函数,该函数在它所嵌套的函数内的变量范围内是本地的。

“像这样定义 Animal 函数与两种项目符号方式中的一种相比有什么优势?”

鉴于显示的代码,没有特别的优势,但如果该外部函数内部还有其他变量,则该内部函数可以引用它们以提供对它们的受控访问(因为这些变量将无法从该外部函数外部访问)

这是可能的,因为 JavaScript 函数形成了所谓的闭包,这意味着即使从该变量范围中删除,它们也会携带其原始变量范围。

奖金问题这些是等价的吗?”

到原始代码?是的,它们基本上是等价的。

主要是对彼此。主要区别在于函数声明(方法 1)是“提升的”,这意味着它们在其范围的顶部可用,因此您可以在定义它们之前实际使用它们。

函数表达式仅在对表达式求值后可用。


请注意,所有函数都有名称,因此它们都会显示在调试控制台中。此外,所有函数最终都在同一个变量范围内。

于 2013-04-22T16:08:11.000 回答