你了解javascript中的function嗎?(1)


上一篇文章中 介紹了function在javascirpt作為一等公民所擔任的重要責任,在不同 的上下文中它擔任着不同的角色,
在對象內部它可以是函數,同時又能充當名字空間,不僅如此所有的function都是閉包。看起來它的確是了不得,
不過除 此之外,function還能擔當構造函數,亦或者說它同時還是一個類的聲明。

這篇文章的目的向大家詳細介紹function是如何作為構造函數

如何定義一個函數

  • 聲明式

函數定義最常用的方式之一。

 1 //聲明函數
 2 function add(x, y) {
 3     return x + y;
 4 }
 5 
 6 //聲明構造函數
 7 function Animal(name, age) {
 8     this.name = name;
 9     this.age = age;
10 }
11 
12 Animal.prototype.bark = function() {return 'bark'};

其實這兩種發式完全一樣,沒有任何區別,你同樣可以為add的prototype屬性增加新的函數或者屬性。
不過兩種方式是基於不同的用途產生的,我們之所以稱后者為構造函數,僅僅因為它的命名函數實現

命名: 對於構造函數我們遵循首字母大學的規則以區別普通函數和方法,這和java中對於類的定義是非常相似的。
實現: 構造函數是我們用來生產實例對象的工具,它通長與new關鍵字連用,如

1 var dog = new Animal('pipi', 3);
2 dog; // Animal {name: "pipi", age: 3}

同時你可能也注意到了Animal中使用到了this關鍵字,通長情況下this會指向函數的調用對象,
也就是說如果你在瀏覽器中運行一下代碼,你應該得到window對象:

1 function getThis() {return this};
2 getThis(); //window

試想一下,如果你這樣使用構造函數:

1  var dog = Animal('pipi', 3); 

這段代碼會產生什么有趣的結果呢?
恭喜你!你中招了!
你會發現,你的window對象新增加了兩個屬性, 同時沒有任何對象產生:

1 window.name === 'pipi'; //true
2 window.age === 3        //true
3 dog === undefined;      //true

對比使用構造函數的兩種方式,其實這都是new在作怪,當我們在像使用java類那樣對構造函數new出javascript對象時,
它幫我們完成了一些magic(這也是javascript new關鍵字被人詬病的地方),我們不妨來一次魔術揭秘:

//魔術
var dog = new Animal('pipi', 3);

//揭秘
function newAlternative(constructor, name, age) {
    var obj = {};
    //修改this,指向新對象obj
    constructor.call(obj, name, age);
   //使實例對象繼承構造函數
    obj.__proto__ = constructor.prototype;
    return obj;
}
var dog = newAlternative(Animal, 'pipi', 3);
dog; //Animal {name: "pipi", age: 3, bark: function}

因此,我們需要非常細心的處理函數,如果它就是‘類’那么請根據潛規則,首字母大寫它,並且在使用的時候一定要與new連用。

  • 匿名

匿名函數廣泛在javascript代碼中使用,先看看這段代碼:

 1 //定義處理元素的匿名函數
 2 [1,2].map(function(e) {return e + 2});
 3 
 4 //定義匿名構造函數
 5 var Animal = function(name, age) {
 6     this.name = name;
 7     this.age = age;
 8 }
 9 Animal.prototype.bark = function() {return 'bark'};
10 
11 Animal.name === ''; //true
  • Function

相對與前兩種方式,使用Function來定義一個新的function相對少見。如果說構造函數是為生成實例對象而生,
那么Function就是為生成函數而生,它是生成函數的模板,構造函數,‘類’.

1 var Animal = 
2 new Function('name', 'age', 'this.name = name; this.age = age;');
3 Animal.prototype.bark = function() {return 'bark'};

雖然這種方式在實際開發中很少被用到,但是它對我們理解函數的生成過程有幫助作用,對比一下兩組代碼,
我們不難發現Animal其實就是Function的實例對象,就如同dog是Animal的實例對象一樣。

1 Animal.__proto__ === Function.prototype //true
2 
3 var dog = new Animal('pipi', 3);
4 dog.__proto__ === Animal.prototype;     //true

總結

函數在javascirpt中起着至關重要的作用,構造函數是其中一種特殊的函數,他通過和new關鍵字搭配使用,
幫助我們完成看起來與普通面向對 象相似的對象構造過程,不過這僅僅是想像而已,我們必須理解其中的奧秘才能是我們不會在編碼過程中犯錯。
有了對函數的理解,接下來我們變可以將解javascript中的另外一個非常關鍵的語言特性,繼承機制–原型鏈,敬請期待。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM