这个Animal =动物动物做什么?

时间:2013-04-22 16:03:17

标签: prototypal-inheritance prototype-programming javascript

我正在尝试理解CoffeeScript生成的这个JavaScript代码。

我习惯于将功能定义为:

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

但CoffeeScript产生以下内容:

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

  return Animal;

})();

问题:

  • 在匿名函数中创建“命名”函数有什么作用?
  • 定义像这样的动物功能与两种项目符号之一有什么好处?

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

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

4 个答案:

答案 0 :(得分:1)

  

定义像这样的动物功能有什么好处?   两种项目符号之一?

  1. 该函数仍将具有显示在调试控制台中的名称
  2. 尽管有一个名字,但该函数不会污染全局命名空间,因为它的范围是匿名包含函数的本地范围,并且它可以作为闭包使用。
  3. 关于你的奖金问题:

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

答案 1 :(得分:1)

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

    <强>更新

    这只是true for IE8 because of the JScript Bug,在现代(和理智)浏览器中使用命名函数表达式时,Animal未在上下文命名空间中注册。

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

    var Tiger = function Animal() {};
    

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

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

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

  2. 定义像这样的动物功能与两种项目符号之一有什么好处?

    <强>更新

    同样,如果适用于比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 declarations can not overwrite function expressions:函数声明在脚本加载的上下文中加载,而表达式赋值在脚本执行时执行:

    function a() { 
      var b = function() { return 3; }; 
      return b(); 
      function b() { return 9; } 
    }
    
    a() //=> returns 3;
    

答案 2 :(得分:0)

  

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

它只是创建一个新函数,该函数是嵌套函数内变量作用域的本地函数。

  

“定义像这样的动物功能与两种项目符号之一有什么好处?”

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

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

  

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

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

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

只有在评估表达式后,才能使用函数表达式。


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

答案 3 :(得分: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中,实际上并没有 class 的概念,只有对象的概念。所以在这里你创建一个变量,然后你分配以下函数的结果

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

然后,定义constructor,并返回包含此函数的对象。

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

希望有所帮助。