1

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

使用“函数声明”在 Javascript 中声明一个普通函数,例如

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

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

还是只有在调用函数构造函数时才创建对象

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

4 回答 4

3

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

你可以这样做:

function foo() {
    return true;
}

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

foo.talk();

函数对象具有与普通 javascript 对象相同的所有功能,但它还可以做一些额外的事情,例如用作构造函数,并且它具有一些内置属性。有关它具有的其他属性/方法的描述,请参阅函数对象的MDN 页面。

于 2012-06-24T06:07:06.503 回答
2

Let's go through the execution line by line, adding line 8 for a better understanding:

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

Line 1 executes, the heap now contains one element, a function object named Foo. At this point, Foo hasn't executed. Lines 2 through 5 aren't executed at this point but are used as the body of Foo. Since Foo hasn't been called, line 3 hasn't been called on any object so nothing has a prop1.

Line 7 executes, the interpreter does several things:

  1. It adds a new object to the heap.
  2. It gives this object the prototype chain of Foo. This does nothing special in the case of Foo since we haven't assigned anything to Foo's prototype, but Foo inherits from Object, so the object now has methods like hasOwnProperty and toString.
  3. The interpreter calls Foo passing the newly created object as this.
  4. Line 3 gets executed, assigning 20 the property named prop1. Whether this creates a new object in the physical heap or if it gets assigned to a primitive section of the object really depends on how the interpretter optimizes everything. I'm sure V8 avoids adding an object to the heap.
  5. The new object gets assigned to a in the variable scope of a.

So basically, creating a function adds the function loader to the heap (or possibly stack depending on scope and optimizations), and executing new Foo adds a new object to the stack.

But what if we didn't use new?

For fun, lets see the different behavior when we don't use new. When line 8 executes, since we aren't calling new we perform a normal function call and don't create a new object. The following happens:

  1. We call Foo on line one. Since we aren't in strict mode, this is assigned to the global window object.
  2. Line 3 executes, assigning window.prop1 = 20.
  3. The function returns undefined.
  4. b is set to undefined.
于 2012-06-24T06:31:14.000 回答
2

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

仅当您实际调用函数时才会创建实例,new并且在此之前,您分配给的属性在this任何地方都不存在。

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

于 2012-06-24T06:02:10.013 回答
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

现在我们有 2 个对象,Foo它们bar引用了一个使用 Foo 作为带有 new 的构造函数创建的对象。所以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
于 2012-06-24T06:18:05.520 回答