Javascript 中 Function 三大用途

JavaScript中的Function對象是函數,Script中的Function(函數)對象的有三大用途。JavaScript中的Function對象是函數,函數的用途分爲3類:編程

  a.做爲普通邏輯代碼容器;b.做爲對象方法;c.做爲構造函數。瀏覽器

1.做爲普通邏輯代碼容器app

      function multiply(x,y){  returnx*y;  } 函數multiply封裝了兩位數的乘法運算公式:函數

      var  product=multiply(128,128);//product=16384   建立函數實例的方式有3種。第一種是聲明式,即像聲明變量同樣,將經過function(){}標識符建立的匿名函數直接賦值給變量,以該變量做爲調用時的函數名稱:this

      var  multiply=function(x,y){  returnx*y;  } 第二種是定義式,即以function關鍵字後跟函數名稱及(){}來直接定義命名函數,前面第一個multiply函數就是經過定義式建立的。url

      第三種是構造函數式,即經過new運算符調用構造函數Function來建立函數。這種方式極不經常使用。prototype

在建立函數的3種方式中,聲明式和定義式還存在細微的差異。好比下列代碼中的函數採用聲明式:對象

    var  example=function(){  return1;  }  example();  varexample=function(){  return2;  }  example();    執行結果以下:繼承

   1  2 而若是採用定義式,即:ip

function example(){  return1;  }  example();  functionexample(){  return2;  }  example(); 那麼會獲得另外一種結果:

  2  2 即,在採用定義式建立同名函數時,後建立的函數會覆蓋先建立的函數。這種差異是因爲JavaScript解釋引擎的工做機制所致使的。JavaScript解釋引擎在執行任何函數調用以前,首先會在全局做用域中註冊以定義式建立的函數,而後再依次執行函數調用。因爲註冊函數時,後定義的函數重寫了先定義的函數,所以不管調用語句位於何處,執行的都是後定義的函數。相反,對於聲明式建立的函數,JavaScript解釋引擎會像對待任何聲明的變量同樣,等到執行調用該變量的代碼時纔會對變量求值。因爲JavaScript代碼是從上到下順序執行的,所以當執行第一個example()調用時,example函數的代碼就是首先定義代碼;而當執行第二個example()調用時,example函數的代碼又變成了後來定義的代碼。

2.做爲對象方法

   JavaScript在解析代碼時,會爲聲明或定義的函數指定調用對象。所謂調用對象,就是函數的執行環境。若是函數體內有以關鍵字this聲明的變量,則this引用的就是調用對象。

事實上,在普通的函數中,也存在調用對象,只不過這個調用對象是默認的全局window對象而已。例如:

   var  product=window.multiply(128,128);//product=16384

   這說明,默認狀況下,在全局做用域中定義或聲明的函數的調用對象就是window。

   在面向對象編程中,一般將做爲對象成員的函數稱爲方法。例如:

   var dog={};  dog.name=「heibao」;  dog.age=「3months」;  dog.shout=function(){  return「Hello,Mynameis「+this.name+」andIam」+this.age+」old!」;  }       dog.shout();//「Hello,MynameisheibaoandIam3monthsold!」    對象也能夠借用其餘對象的方法:

   var cat={};  cat.name=「xiaohua」;  cat.age=「2years」;  cat.greet=dog.shout;  cat.greet();//「Hello,MynameisxiaohuaandIam2yearsold!」 另外,使用函數對象的call和apply方法,還能夠動態指定函數或方法的調用對象:

   dog.shout.call(cat);  //「Hello,MynameisxiaohuaandIam2yearsold!」    或者    dog.shout.apply(cat);  //「Hello,MynameisxiaohuaandIam2yearsold!」

3.做爲構造函數 JavaScript是經過構造函數來模擬面嚮對象語言中的類的。例如:

   function  Animal(sort,character){  this.sort=sort;  this.character=character;  } 以Animal做爲構造函數,就能夠像下面這樣建立一個新對象:

   var  dog=newAnimal(」mammal」,」fourlegs」);    建立dog的對象的過程以下:首先,new運算符建立一個空對象({}),而後以這個空對象爲調用對象調用函數Animal,爲這個空對象添加兩個屬性sort和character,接着,再將這個空對象的默認constructor屬性修改成構造函數的名稱(即Animal;空對象建立時默認的constructor屬性值是Object),而且將空對象的__proto__屬性設置爲指向Animal.prototype——這就是所謂的對象初始化。最後,返回初始化完畢的對象。這裏將返回的新對象賦值給了變量dog。

dog.sort;//mammal  dog.character;//fourlegs  dog.constructor;//Animal 聰明的讀者結合前面介紹的內容,可能會認爲使用new運算符調用構造函數建立對象的過程也能夠像下面這樣來實現:

   var  dog={};  Animal.call(dog,「mammal」,」fourlegs」); 表面上看,這兩行代碼與var  dog=newAnimal(」mammal」,」fourlegs」);是等價的,其實卻不是。雖然經過指定函數的執行環境可以部分達到初始化對象的目的,例如空對象dog確實得到了sort和character這兩個屬性:dog.sort;//mammal  dog.character;//fourlegs  dog.constructor;//Object——注意,沒有修改dog對象默認的constructor屬性 可是,最關鍵的是新建立的dog對象失去了經過Animal.prototype屬性繼承其餘對象的能力。只要與前面採用new運算符調用構造函數建立對象的過程對比一下,就會發現,new運算符在初始化新對象期間,除了爲新對象添加顯式聲明的屬性外,還會對新對象進行了一番「暗箱操做」——即將新對象的constructor屬性重寫爲Animal,將新對象的__proto__屬性設置爲指向Animal.prototype。雖然手工「初始化對象」也能夠將dog.constructor重寫爲Animal,但根據ECMA262規範,對象的__proto__屬性對開發人員是隻讀的,對它的設置只能在經過new運算符建立對象時由JavaScript解釋引擎替咱們完成。 JavaScript是基於原型繼承的,若是不能正確設置對象的__proto__屬性,那麼就意味着默認的繼承機制會失效:

Animal.prototype.greet=「Hi,goodlucky!」;  dog.greet;//undefined 事實上,在Firefox中,__proto__屬性也是可寫的:

Animal.prototype.greet=「Hi,goodlucky!」;  dog.__proto__=Animal.prototype;  dog.greet;//Hi,goodlucky! 但這樣作只能在Firefox中行得通。考慮到在兼容多瀏覽器,必須依賴於new運算符,才能實現基於原型的繼承。

相關文章
相關標籤/搜索