1.對象javascript
在javascript裏,一切都是對象,包括函數自身(不是指具體的函數,而是指"Function"這個東東)。
例如:java
var fun1=new Function("num1","num2","alert(num1+num2)");
這時,fun1是一個函數的"實例",或者說函數對象,因此固然是一個對象。fun1.__proto__指向Function.prototype。
但同時,Function也有__prototype__:c#
因此,從這個則面能夠看出,"Function"本身也是一個對象,它的__prototype__是建立"Function"的prototype,只不過是js引擎內核來實現,屬於創世者的角色。
這個就有點像c#裏的元數據同樣,元數據定義了類,但元數據自己也能夠用具體的類來體現(反射建立類的時候用得最多)
正由於javascript能夠在語言自己和定義自己之間任意地切換,甚至不少狀況下,語言自己和定義自己同爲一體,在c#這類靜態語言裏,若是不經過反射這種「超維度」手段,你不能知道一個類定義了多少個成員。但js裏,代碼裏能夠用數組輕鬆遍歷一個對象的全部屬性,也能夠自由地爲對象添加成員,因此才被成爲「動態語言」。數組
2.函數app
一切的對象都能由函數創造,包括函數自身。
函數和對象是javascript世界裏的兩大核心。
函數能夠做爲一個普通的函數,例如:
var add=function(a,b){return a+b;}
也能夠做爲對象的構造函數,例如:函數
var Person=function(name,age){ this.name=name, this.age=10; this.selfIntro=function(){console.log("hi, i am "+this.name+", i am "+this.age+" years old")} } var tom=new Person("tom",10); tom.selfIntro();
一個函數做爲普通函數時和做爲構造函數時,語法上面沒有任何不一樣。甚至一個函數裏即存在一段"普通函數"的代碼,同時有有一段用於"構造對象"的代碼。
但做爲普通函數時和做爲構造函數時,函數裏的"this"的指向時不一樣的(在下邊介紹)。this
因此實際上,spa
var obj=new Object(); var str=new String("haha"); var birthday=new Date(2019,5,6); var fun1=new Function("num1","num2","alert(num1+num2)");
以上這些對象,都是經過函數來構造的。這些函數就是Object,String,Date和Function。固然,這些函數本身又是一個對象。prototype
3.原型:
在javascript裏,每一個函數對象都有一個原型(prototype)。這裏說的"函數對象"是指使用typeof 命令顯示出"function"的對象。若是 var obj={},由於obj只是一個對象,不是一個函數,因此obj.prototype是undefined。
但雖然非函數對象沒有prototype屬性,但任何一個對象都有__proto__屬性,指向構造該對象的函數的prototype。(但__proto__不是語言標準裏定義的東西,因此一些js環境裏可能不支持)。code
經過prototype,能夠實現對象的繼承。
在javascript中,調用一個對象的屬性(包含方法)時,會先在對象自身尋找該屬性。若是對象自身沒有,則會在對象自身的__proto__上找,若是自身的__proto__沒有,則會在自身__proto__對象的__proto__上找,一直找到盡頭。
4.this:
javascript 的this 指向哪一個對象,依賴於當前的上下文:
狀況一:純粹的函數調用,則this指向上層對象。
例如,
var fun=function(){console.log(this)};
這裏的this指向window對象。相似地 <script>this</script>,this指向window,由於<script>標籤裏的執行上下文也是window。
而:
var a={x:1,m:function(){alert(this.x)}};
那麼這時的this指向a這個對象。
狀況二:做爲構造函數調用時,this指向這個構造函數產生的新對象。
var Person=function(){this.name="tom";this.showName=function(){console.log(this.name)}}; var p1=new Person(); p1.showName();//tom
狀況三:使用call或者apply 調用
一般,一個函數做爲非構造函數的時候,this指向上級對象。有沒有辦法能夠指定指向某個對象呢?答案是能夠。方法是經過call()或apply:
var fun1=function(){this.name="tom"};
這時,若是執行fun1(),那麼 fun1內部的this執行window對象,因此window.name=="tome"。
這是:
var obj={}; fun1.call(obj)
這時,fun1內部的this指向到obj這個對象。因此,obj.name=="tom"
btw: call和aplly的區別只是參數的形式不一樣而已。