函数声明是否在Javascript中创建了一个对象?

时间:2012-06-24 05:58:41

标签: javascript

函数构造函数能够在javascript中创建对象但是 我有一个更基本的问题。

使用“函数声明”(例如

)在Javascript中声明普通函数
function Foo() 
{
  this.prop1 = 20;
  //some code
}

这是否在javascript堆内部创建一个对象,指针为abc,prop1为20?

或者只是在调用函数构造函数时才创建对象 像

var a = new Foo() //This definately creates a new object

4 个答案:

答案 0 :(得分:3)

在javascript中,所有函数都是对象。

你可以这样做:

function foo() {
    return true;
}

foo.greeting = "hello";
foo.tone = "mean";
foo.talk = function() {
    alert(foo.greeting);
}

foo.talk();

函数对象具有与普通javascript对象相同的所有功能,但它也可以执行一些其他操作,例如用作构造函数,并且它具有一些内置属性。有关其具有的其他属性/方法的说明,请参阅Function对象上的MDN page

答案 1 :(得分:2)

函数声明只创建函数对象 Foo,但调用函数或创建它的实例。

实例仅在您使用new实际调用该函数时创建,在此之前,您分配给this的属性不存在于任何位置。

也可能是Foo永远不会被称为构造函数。只是通过查看函数,您无法确定某个函数是否用作构造函数。

答案 2 :(得分:2)

让我们逐行完成执行,添加第8行以便更好地理解:

/* 1 */ function Foo() 
/* 2 */ {
/* 3 */   this.prop1 = 20;
/* 4 */   //some code
/* 5 */ }
/* 6 */ 
/* 7 */ var a = new Foo()
/* 8 */ var b = Foo()

第1行执行,堆现在包含一个元素,一个名为Foo的函数对象。此时,Foo尚未执行。此时不执行第2行到第5行,而是用作Foo的主体。由于尚未调用Foo,因此未在任何对象上调用第3行,因此没有prop1

第7行执行,解释器执行以下操作:

  1. 它向堆中添加了一个新对象。
  2. 它为此对象提供了Foo的原型链。这在Foo的情况下没有什么特别之处,因为我们没有为Foo的原型分配任何内容,但Foo继承自Object,因此对象现在有方法例如hasOwnPropertytoString
  3. 解释器调用Foo将新创建的对象传递为this
  4. 第3行被执行,分配20名为prop1的属性。是否在物理堆中创建新对象或者是否将其分配给对象的原始部分实际上取决于解释器如何优化所有内容。我确定V8避免在堆中添加对象。
  5. 新对象在a的变量范围内被分配到a
  6. 所以基本上,创建一个函数会将函数加载器添加到堆中(或者可能是堆栈,具体取决于作用域和优化),并且执行new Foo会向堆栈添加一个新对象。

    但是,如果我们没有使用new

    ,该怎么办?

    为了好玩,让我们在不使用new时看到不同的行为。当第8行执行时,由于我们没有调用new,我们执行正常的函数调用而不创建新对象。发生以下情况:

    1. 我们在第一行打电话给Foo。由于我们未处于严格模式,因此this被分配给全局window对象。
    2. 执行第3行,分配window.prop1 = 20
    3. 该函数返回undefined
    4. b设置为undefined

答案 3 :(得分:0)

Javascript有点令人困惑,因为函数既是普通函数,也没有默认上下文,但与new配对,就会创建一个新对象。所以

function Foo() {
    this.prop1 = 20;
}

console.log( typeof(Foo) ); //-> 'function' 

创建一个名为Foo的对象,其类型为function。现在我们可以获取我们的函数对象并创建将添加到当前堆栈的新对象:

var bar = new Foo();
console.log( typeof(bar) ); // -> 'object' with a pointer named prop1 to 20

现在我们有两个对象Foobar,它们引用了一个使用Foo作为构造函数创建的对象。所以new基本上是魔术,是在Javascript中创建对象的三种方法之一。这三种方式是:

var object = {}; // Creates an object using object literal notation
new Foo(); // Creates an object with built in 'new'
Object.create(null); // new ECMA5 notation that avoid using new