javascript Function()

來源:互聯網
上載者:User

JavaScript中的Function對象是函數,函數的用途分為3類:
作為普通邏輯代碼容器;
作為對象方法;
作為建構函式。

1.作為普通邏輯代碼容器
function multiply(x, y) {
  return x * y;
}

函數multiply封裝了兩位元的乘法運算公式:
var product = multiply(128, 128);         // product = 16384

建立函數執行個體的方式有3種。第一種是聲明式,即像聲明變數一樣,將通過function(){}標識符建立的匿名函數直接賦值給變數,以該變數作為調用時的函數名稱:
var multiply = function(x, y) {
    return x * y;
}

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

第三種是建構函式式,即通過new運算子調用建構函式Function來建立函數。這種方式極不常用,因此就不作介紹了。

在建立函數的3種方式中,聲明式和定義式還存在細微的差別。比如下列代碼中的函數採用聲明式:
var example = function(){
    return 1;
}
example();

var example = function(){
    return 2;
}
example();

執行結果如下:
1
2

而如果採用定義式,即:
function example() {
    return 1;
}
example();

function example() {
    return 2;
}
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   = "3 months";

dog.shout = function() {
  return "Hello, My name is" + this.name + "and I am" + this.age + "old!";
}
dog.shout(); // “Hello, My name is heibao and I am 3 months old!”

有意思的是,對象也可以借用其他對象的方法:
var cat   = {};
cat.name  = "xiaohua";
cat.age   = "2 years";
cat.greet = dog.shout;
cat.greet();          //“Hello, My name is xiaohua and I am 2 years old!”

另外,使用函數對象的call和apply方法,還可以動態指定函數或方法的調用對象:

dog.shout.call(cat);  //“Hello, My name is xiaohua and I am 2 years old!”
或者
dog.shout.apply(cat); //“Hello, My name is xiaohua and I am 2 years old!”

3.作為建構函式
JavaScript是通過建構函式來類比物件導向語言中的類的。例如:
function Animal(sort, character) {
   this.sort = sort;
   this.character = character;
}

以Animal作為建構函式,就可以像下面這樣建立一個新對象:
var dog = new Animal("mammal", "four legs");

建立dog的對象的過程如下:首先,new運算子建立一個Null 物件({}),然後以這個Null 物件為調用對象調用函數Animal,為這個Null 物件添加兩個屬性sort和character,接著,再將這個Null 物件的預設constructor屬性修改為建構函式的名稱(即Animal;Null 物件建立時預設的 constructor屬性值是Object),並且將Null 物件的__proto__屬性設定為指向Animal.prototype——這就是所謂的對象初始化。最後,返回初始化完畢的對象。這裡將返回的新對象賦值給了變數dog。

dog.sort;        // mammal
dog.character;   // four legs
dog.constructor; // Animal

聰明的讀者結合前面介紹的內容,可能會認為使用new運算子調用建構函式建立對象的過程也可以像下面這樣來實現:

var dog = {};
Animal.call(dog, "mammal", "four legs");

表面上看,這兩行代碼與var dog = new Animal("mammal", "four legs");是等價的,其實卻不是。雖然通過指定函數的執行環境能夠部分達到初始化對象的目的,例如Null 物件dog確實獲得了sort和character這兩個屬性:

dog.sort;        // mammal
dog.character;   // four legs
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, good lucky!";
dog.greet; // undefined

事實上,在Firefox中,__proto__屬性也是可寫的:

Animal.prototype.greet = "Hi, good lucky!";
dog.__proto__ = Animal.prototype;
dog.greet; // Hi, good lucky!

但這樣做只能在Firefox中行得通。考慮到在相容多瀏覽器,必須依賴於new運算子,才能實現基於原型的繼承

 

轉載於:http://blog.sina.com.cn/s/blog_81adceb001012n51.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.