函数构造函数能够在javascript中创建对象但是 我有一个更基本的问题。
使用“函数声明”(例如
)在Javascript中声明普通函数function Foo()
{
this.prop1 = 20;
//some code
}
这是否在javascript堆内部创建一个对象,指针为abc,prop1为20?
或者只是在调用函数构造函数时才创建对象 像
var a = new Foo() //This definately creates a new object
答案 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行执行,解释器执行以下操作:
Foo
的原型链。这在Foo
的情况下没有什么特别之处,因为我们没有为Foo
的原型分配任何内容,但Foo
继承自Object
,因此对象现在有方法例如hasOwnProperty
和toString
。Foo
将新创建的对象传递为this
。prop1
的属性。是否在物理堆中创建新对象或者是否将其分配给对象的原始部分实际上取决于解释器如何优化所有内容。我确定V8避免在堆中添加对象。a
的变量范围内被分配到a
。所以基本上,创建一个函数会将函数加载器添加到堆中(或者可能是堆栈,具体取决于作用域和优化),并且执行new Foo
会向堆栈添加一个新对象。
但是,如果我们没有使用new
?
为了好玩,让我们在不使用new
时看到不同的行为。当第8行执行时,由于我们没有调用new
,我们执行正常的函数调用而不创建新对象。发生以下情况:
Foo
。由于我们未处于严格模式,因此this
被分配给全局window
对象。window.prop1 = 20
。undefined
。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
现在我们有两个对象Foo
和bar
,它们引用了一个使用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