2012-06-24 55 views
1

函數構造函數能夠在javascript中創建對象,但是 我有一個更基本的問題。函數聲明是否在Javascript中創建對象?

聲明在使用「函數聲明」如

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

這是否創建一個對象內部的Javascript純功能的JavaScript堆與指針爲abc和PROP1 20?

或者是所創建的對象只有當函數調用構造函數 像

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

回答

3

在javascript中,所有函數都是對象。

你可以做這樣的事情:

function foo() { 
    return true; 
} 

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

foo.talk(); 

函數對象擁有所有相同的功能,作爲一個正常的JavaScript對象,但它也可以做一些額外的東西,如被用來構造函數,它有一些內置的屬性。請參閱Function對象上的MDN page以獲取對其具有的其他屬性/方法的描述。

+0

給定一個變量如何判斷它是一個函數對象還是使用javascript代碼的普通對象? – seahorse

+1

@seahorse:用'typeof'。它將返回函數''功能''。 –

+1

您也可以執行'myFunction instanceof Function'或'myFunction.constructor == Function' –

2

函數聲明只創建函數對象Foo,但它確實調用功能或創建它的一個實例。

僅當實際調用new函數時才創建實例,直到此時,您分配給this的屬性在任何地方都不存在。

也可能很好,Foo永遠不會被稱爲構造函數。只要看一個函數,就不能確定一個函數是否被用作構造函數。

+0

javascript中的函數對象和普通對象有什麼不同? – seahorse

+0

JavaScript中的所有內容都是一個對象。所以在內部,函數也是對象,但具有特殊的屬性(它們是可調用的)。 「普通」對象不可調用。 –

+1

重要的是要知道,雖然一切都是「對象」,但並非所有事物都是「對象」。 'true'不是一個Object,而'new Boolean(true)'是。字符串,布爾值和數字會自動裝箱以處理現有的屬性,但是分配給primative的新屬性立即被丟棄。 –

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其中引用使用美孚與新構造函數創建的對象。所以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 
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

因此,基本上,創建一個函數將函數裝載到堆(或可能堆棧取決於範圍和優化),並執行new Foo增加了一個新對象到堆棧中。

但是如果我們不使用new

爲了好玩,當我們不使用new時,可以看到不同的行爲。當第8行執行時,由於我們沒有調用new,我們執行正常的函數調用,並且不創建新的對象。發生以下情況:

  1. 我們在第一行稱爲Foo。由於我們不處於嚴格模式,因此this被分配給全局window對象。
  2. 第3行執行,分配window.prop1 = 20
  3. 該函數返回undefined
  4. b設置爲undefined