2011-05-11 47 views
38

你可以調用一個函數作爲一個對象嗎?例如:javascript:函數和對象...?

function Tip(txt){  
    this.content = txt; 
    this.shown = false; 
} 

和:

var tip = new Tip(elem.attr('title')); 

我的問題:

  1. 你可以叫new的功能,作爲一個對象?
  2. 使用「這個」成爲可能,因爲我們使用作爲一個對象的功能?

回答

108

您正在尋找constructor的概念。

在JavaScript are objects所有功能,可用於創建對象:

function make_person(firstname, lastname, age) { 
    person = {}; 
    person.firstname = firstname; 
    person.lastname = lastname; 
    person.age = age; 
    return person; 
} 
make_person("Joe", "Smith", 23); 
// {firstname: "Joe", lastname: "Smith", age: 23} 

然而,爲了創建特定類型的新對象(也就是說,繼承原型,有一個構造函數等),如果函數new運算符運算符調用,則函數可以引用this,那麼它將返回一個對象,其中包含函數this中定義的所有屬性,在這些情況下引用新對象創建。

function make_person_object(firstname, lastname, age) { 
    this.firstname = firstname; 
    this.lastname = lastname; 
    this.age = age; 
    // Note, we did not include a return statement 
} 

關鍵的區別注意make_personmake_person_object之間是調用new make_person()(而不是簡單地make_person())不會做任何不同......都將產生相同的對象。調用make_person_object()沒有new操作但是,將目前的this對象定義this屬性

因此(通常window如果你在瀏覽器中運行。):

var Joe = make_person_object("Joe", "Smith", 23); 
console.log(Joe); // undefined 
console.log(window.firstname) // "Joe" (oops) 

var John = new make_person_object("John", "Smith", 45); 
console.log(John); // {firstname: "John", lastname: "Smith", age: 45} 

此外,作爲@RobG指出,這種做事方式會在我們創建的每個「人」上創建對make_person_objectprototype財產的引用。這使我們可以添加方法和事後屬性人數:

// Assuming all that came before 
make_person_object.prototype.full_name = "N/A"; 
make_person_object.prototype.greet = function(){ 
    console.log("Hello! I'm", this.full_name, "Call me", this.firstname); 
}; 
John.full_name // "N/A" 
John.full_name = "John Smith"; 
make_person_object.full_name // Still "N/A" 
John.greet(); // "Hello! I'm John Smith Call me John" 

公約有它像make_person_object該構造函數資本,單一化和「nouned」(因爲缺乏一個更好的詞) - 因此,我們將有一個Person的構造函數,而不是make_person_object,它可能被誤認爲是一個普通的函數。

參見:

+6

您省略了最重要的部分:由構造函數的'this'引用的新對象繼承構造函數原型的屬性。 – RobG 2011-05-11 03:29:19

+2

@RobG - 好吧,我*做*!我已經更新了答案,其中包含一些示例 - 感謝您幫助它變得更好! – 2011-05-11 03:40:17

+1

夢幻般的答案。真的很棒。涵蓋了做什麼,然後教我如何理解它。之後我讀過的每個問題都會在後面的章節中回答。謝謝!! – redfox05 2016-03-04 20:50:42

15

每個函數都有對this的引用。如果您撥打Tip(),則this將引用全局對象。如果您調用new Tip(),則會創建一個引用Tip.prototype的新對象,並且this將引用該新對象。

您不能在對象上使用new,例如new {}將引發TypeError: object is not a function。如果你指的是new Object()那麼它的工作原理是Object是一個函數。

1

該函數充當一個類的構造函數。或者,你可以這樣做:

function Tip(txt) { 
return { 
content: txt, 
shown: false 
} 
} 

,並得到一個新實例:var myTip = new Tip("my epic tip"); 這是類似的,比方說,C#:

public class Tip { 
string text = ""; 
public Tip(string txt) { 
text = txt; 
} 
} 

因此,排序的。 1)由於函數本質上充當一個類,所以你正在調用new,並且2)this指的是類的當前實例。

+2

該函數不用作對象。使用'new'時會創建一個新對象,並且在該函數 – 2011-05-11 02:13:29

+0

@Adam右側的範圍內調用該函數。我撇清了他的問題的確切用語。學過的知識。 ;-) – 2011-05-11 02:15:35

+0

@Adam:另一種創建對象的方法是像托馬斯那樣使用對象字面值語法。使用「新」只是創建對象的方法之一。 – user670800 2011-05-11 02:22:43

1

#1:有一個對象調用功能(大寫F)

變種F =新功能( 「X」, 「Y」, 「返回X * Y;」);

對於#2:「this」根據不同的位置模式而不同(如Douglas Crockford所述)。 Crockford表示有4種模式(方法模式,函數模式,構造函數模式和「應用」模式)

+0

,它調用eval並且不會比創建函數的功能更強大。這個問題似乎也沒有關係。 – 2011-05-11 02:11:25

+0

不知道這與OP有什麼關係(也許它只是我的壽命)。可能想要在傾訴投入前澄清。 – 2011-05-11 02:11:45

+0

@亞當:它不叫eval。如果您仔細閱讀,答案與他的#1問題有關。 – user670800 2011-05-11 02:16:53

5

是。在JavaScript中,技術上所有東西都是一個對象。當你使用new時,它會創建一個Tip對象的實例,然後像調用構造函數一樣調用Tip函數。

如果你要的功能添加到提示的對象,你應該將它們添加到提示的原型就像這樣:

Tip.prototype.getContent = function() { 
    return this.content; 
}; 

如果你有,然後你做:

var tip = new Tip("this is my content."); 
alert(tip.getContent()); 

它會顯示一條消息,說「這是我的內容」。

但是,如果對象具有功能實現,則只能使用new。所以這是行不通的:

var Tip = { content: txt, show: false }; 
var tipObj = new Tip(); 
0
  1. 事實上,每一個數據類型,例如數組,函數是對象。
  2. 當我們把函數作爲一個類聲明的時候,這是有效的。
0

我已經努力去理解近8年(2008-2016)這些概念(函數作爲對象,原型對象,__proto__屬性,構造函數屬性)。首先,我在多次閱讀第6,8,9章之後開始了David Flanagan的「JavaScript權威指南第5版/第6版」,時間爲4-5年;它對我來說沒有任何意義,但在互聯網上掙扎後,我能夠將一些功能(具有屬性的典型C++功能)作爲對象進行管理;因爲對象也可以有方法。幸運的是,在2015年的第7年,我開始了Wrox Nicholas C.Zakas「面向Web開發人員的專業JavaScript第三版」第6,7章;這對理解以上四個概念非常有幫助。傳統上在C/C++/C#函數中被認爲是修改一個對象;或者換句話說,它們是爲了「做某事」而製作的,其中對象是用於維護全局運行上下文的狀態以及用於改變它自己的對象狀態的方法。所以如果函數可以是第一類對象,那麼爲什麼對象不能像函數一樣?

這裏的主要關鍵問題應該是爲什麼?爲什麼不像「關聯函數」或「鏈式參數」那樣,單個概念實體 ?這是我的理解: 瀏覽器EXE是一個單線程應用程序,這個EXE控制調用JS解釋器預定義的作用域鏈(有些類似於帶有參數的命令字符串);現在在運行時,JS引擎(而不是解釋器)以提升方式加載代碼(因爲沒有主要方法來提升定義好的密鑰代碼及其調用)。在這個提升的代碼中,如果函數不被視爲對象,那麼它們必須在單獨的調用上下文(超出作用域鏈)上維護,這很容易在c/C++/c#(多線程和無限內存的bcoz)中實現,但不能在JS 。因此,「鏈接對象上的待辦事項」使Java腳本函數成爲第一類對象。實際上JS對象也是這樣做的;唯一的區別是「調用一個對象」並不存在於「調用一個函數」的對象中,這是有道理的。函數也可以被認爲是「帶有地址鏈接(鏈)的彙編語言指令的一堆變量」。鏈接部分是故事的另一端 - 頂部 - >底部鏈接(原型對象)與底部 - >頂部鏈接(__ proto__屬性)vs對象藍色 - >對象實例(構造函數屬性)。幾個月前,我發現下面的圖片有助於理解鏈接。

http://judis.me/wordpress/wp-content/uploads/2015/08/JavaScriptDiagram.png「JS Object model」