回到了本身的家鄉,期待中有感受到了不少的陌生,一個有「故事」的環境中,你我是否「孤獨」!
在我看來function共有三種類型,做爲對象使用,處理業務以及穿件object的實例對象。跟這三種用法相對應的有三種子類型,分別是對象的屬性、變量(包括參數)和建立出來的object類型實例對象的屬性。這三種子類是相互獨立的,並且也很容易區分。可是,咱們剛剛接觸的時候很容易混淆。javascript
這種狀況下,function對象的子類型就是對象本身的屬性,這時經過操做符「.」(或者方括號操做符)使用,示例以下:java
function book(){} book.price=999; book["getPrice"]=function(){ return this.price; } console.log(book.getPrice()); //輸出結果:999
我不多碰到function來做爲object類型的對象來使用。
這種狀況下,function的子類型就是本身定義的局部變量(包括參數),這時的變量實在方法被調用時經過變量做用域鏈來管理的。
關於變量我以前的文檔中有涉及到,這裏就不過多的說明了。閉包
這種狀況下,對應的子類型是使用function建立實例對象的屬性(很經常使用),主要包括在function中經過this添加屬性,以及建立完成以後實例對象本身添加的屬性。另外,還能夠調用function的prototype屬性對象所包含的屬性,示例以下:函數
function Car(color,displacement){ this.color = color; this.displacement = displacement; } Car.prototype.logMessage = function(){ console.log(this.color+","+this.displacement); }; var car = new Car("yellow","2.4T");//看看是否是相似構造函數?哈哈
這個例子中建立的car對象就包含有color和displacement兩個屬性,並且還能夠調用Car.prototype的logMessage方法。固然,建立完以後還可使用點操做符給建立的car對象添加或者修改屬性,也可使用delete刪除其中的屬性,示例以下:測試
function Car(color,displacement){ this.color = color; this.displacement = displacement; } //全部建立出來的car都有該方法 Car.prototype.logMessage = function(){ console.log(this.color+","+this.displacement); }; var car = new Car("yellow","2.4T");//看看是否是相似構造函數?哈哈 //給car對象添加屬性 car.logColor = function(){ console.log(this.color); }; //完成調用測試 car.logColor();//輸出結果: yellow car.color = "red"; car.logColor();//輸出結果:red delete car.color;//刪除屬性 car.logColor();//輸出結果:undefined
代碼分析:在建立完car對象以後,又給它添加了logColor的方法,能夠打印car的color屬性。添加完logColor方法後直接調用就能夠打印出car原來的color屬性值(yellow)。而後,將其修改成red,在打印出了red。最後,使用delete刪除car的color的屬性,這時在調用logColor方法會打印出undefinedthis
其實跟個人註釋說明一致!!!prototype
function的三種子類型是相互獨立的,他們只能在本身所對應的環境中使用而不能相互調用,示例以下:code
function log(msg){//第二種業務處理 console.log(msg); } function Bird(){ var name = "kitty"; this.type = "pigeon"; this.getName = function(){ return this.name;//建立的對象沒有name屬性 } } Bird.color = "white";//第一種object類型的對象 Bird.getType = function(){//第一種object類型的對象 return this.type; }; Bird.prototype.getColor = function(){//第三種建立對象 return this.color; } var bird = new Bird(); log(bird.getColor());// undefined log(bird.getName()); // undefined log(bird.getType()); // undefined
Bird 做爲對象時包含 color 和 getType 兩個屬性,做爲處理業務的函數是包含一個名爲name的局部變量,建立的實例對象bird具備type和getName兩個屬性,並且還能夠調用Bird.prototype的getColor屬性,getColor也能夠看做bird的屬性。
用 法 | 子 類 型 |
---|---|
對象(Bird) | color 、getType |
處理業務(Bird方法) | name |
建立實例對象(bird) | type、getName、(getColor) |
每種用法中所定義的方法只能調用相對應所對應的屬性,而不能交叉調用,從對應關係中能夠看出,getName、getColor和getType三個方法中沒法獲取到值,你們再仔細分析一下!對象
另外,getName和getColor是bird的屬性方法,getType是Bird的屬性方法,若是用Bird對象調用getName或getColor方法或者使用bird對象調用getType方法都會拋出找不到的錯誤。繼承
三種子類型不能夠相互進行調用以外,還有一種狀況也很是重要:那就是對象的屬性並無繼承的關係。
function obj(){} obj.v=1; obj.func = { logV : function(){ console.log(this.v); } } obj.func.logV();
代碼分析:這個例子中的obj是做爲對象使用的,obj是有一個屬性v和一個對象屬性func,func對象中又有一個logV方法,logV方法用於打印對象的v屬性。這裏須要特別注意:
logV方法打印的是func對象的v屬性,可是func對象中並無v屬性,因此最後結果是undefined。
這個例子中,雖然obj對象中包含v屬性,可是因爲屬性不能夠繼承,因此obj的func屬性對象中的方法不可使用obj中的屬性v.
請你們必定要記住,而且不要和prototype的繼承以及變量做用域鏈相混淆
三種子類型原本是相互獨立、各有各的使用環境的,可是,有一些狀況下須要操做不屬於本身所對應環境的子類型,這時就須要使用一些技巧來實現了。
約定以下
op | v | ip | |
---|---|---|---|
O | 直接調用 | 在函數中關聯到O的屬性 | 不可調用 |
F | 使用O調用 | 直接調用 | 不可調用 |
I | 使用O調用 | 在函數中關聯到I的屬性 | 直接調用 |
橫向表頭表示三種類型,表格的主體表示在function相應用法中調用各類子類的方法。
由於function建立的實例對象在建立以前還不存在,因此function做爲方法(F)和做爲對象(O)使用時沒法調用function建立的實例對象的屬性(ip)。調用參數能夠在函數中將變量關聯到相應的屬性,調用function做爲對象(O)時的屬性能夠直接使用 function 對象來調用
function log(msg){ console.log(msg); } function Bird(){ //私有屬性 var name = "kitty"; var type = "pigeon"; //將局部變量name關聯到新建立的對象的getName,setName屬性方法 //閉包可使用局部變量 //公有屬性 this.getName = function(){ return name; } this.setName = function(n){ name = n; } //將局部變量type關聯到Bird對象getType屬性方法 //靜態屬性 Bird.type = function(){ return type; } //在業務處理中調用Bird對象的color屬性 log(Bird.color);//輸出結果: white,F調用op } Bird.color = "white";// 表明 O //在建立出的實例對象中調用Bird對象的color屬性 Bird.prototype.getColor = function(){//I return Bird.color;//OP } var bird = new Bird(); // 建立實例 I log(bird.getColor()); // 輸出結果:white , I 調用 op log(bird.getName());// 輸出結果:kitty , I 調用 v 局部變量 log(Bird.getType());// 輸出結果:pigeon , O 調用 v 局部變量 bird.setName("petter"); // I 調用 v log(bird.getName());// 輸出結果:petter , I 調用 v 局部變量
好好分析上述的代碼,很是經典的,瞭解三種子類型的不一樣環境用法中交叉調用的方法
上面的示例中咱們涉及到了公有屬性、私有屬性和靜態屬性的說明,因爲JS並非基本類而是基於對象的語言,所以JS自己並無這些概念。