聲明函數的方法 之 語句定義法(函數聲明法)和表達式定義法(函數表達式)


一、函數的定義:

在說明什么是函數前先舉一個小例子:

大家都知道印刷術是我國的四大發明(科普一下:中國四大發明:造紙術、印刷術、火葯、指南針)之一,之所以有印刷術,是因為重復的抄寫既浪費時間,效率又很低,所以印刷術應用而生,印刷術就像一個工具,有了這個工具,我們就不需要再重復的去抄寫一些一模一樣的內容。

今天所說的函數就類似於印刷術,我們在書寫代碼時發現,在實現同一個功能時,所用的代碼幾乎是一樣的,因為實際需要,所以不得不重復的去書寫一樣的代碼,這時我們書寫的代碼看起來很冗雜,會占據內存空間,解析的時間也會很長,所以,為了使我們的代碼書寫的更美觀,我們可以將我們的代碼封裝起來,給它一個命名,放在一個獨立的模塊里,需要使用時拿過來就OK了!

比如說我們在不使用任何循環語句直接想打印5次“hello world!”時,這時我們就需要重復輸出5次“hello world!”,代碼如下:

document.write(('hello world!')+"</br>");
document.write(('hello world!')+"</br>");
document.write(('hello world!')+"</br>");
document.write(('hello world!')+"</br>");
document.write(('hello world!')+"</br>");

接下來我們封裝一個函數來打印“hello world!”

function helloworld(){
document.write(('hello world!')+"</br>");
}
helloworld()
helloworld()
helloworld()
helloworld()
helloworld()
很明顯:我們用函數來打印“hello world”,不用再重復的書寫一樣的代碼,只需要使用的時候調用就OK了!
函數的定義:需要反復使用的功能代碼,封裝成一個獨立的模塊,這個模塊就叫函數。

二、聲明函數的方法:

用function來定義函數

我們了解了什么是函數后,接着來看一下怎么聲明函數,通俗點說就是怎么使用這個函數:

1.語句定義法:

其實我們在打印“hello world”時使用的方法就是語句定義法

格式:function 函數名(){

     函數塊;

}

調用:函數名()

2.表達式定義法:

一說表達式,肯定是和賦值有關,我們可以大膽的猜想一下,表達式定義法是不是就是我們將一個函數賦值給了一個變量呢?

看一下它的格式:

var 變量名 = function[函數名](){

    函數塊;

}

調用:變量名()

注意:var后面的是它聲明的這個變量的變量名,不是函數名,函數名還是在function后面,之所以將函數名寫在[]中,是因為在表達式定義法中,函數名是可以省略的,通常情況下,函數名我們也都是省略不寫的。

語句定義法和表達式定義法在以后的使用中,語句定義法會更常用。

為什么說語句定義法更常用呢,這就要說一下語句定義法和表達式定義法的區別了:

3、語句定義法和表達式定義法的區別:

語句定義法會提升函數,會在執行代碼前讀取函數聲明,通俗講就是我們可以在任何位置調用這個函數;

//person() 函數前調用     //張三
function person(){
var name = "張三";
alert(name);
}
person() //函數后調用    //張三

表達式定義法不會提升函數,必須先聲明函數,再調用;

//person(); 報錯:控制台輸出person is not a function
var person = function(){
var name = "張三";
alert(name);
}
person(); //張三

函數聲明運行規則:

函數聲明只能出現在程序或函數體內。從句法上講,它們 不能出現在Block(塊)({ ... })中,例如不能出現在 if、while 或 for 語句中。因為 Block(塊) 中只能包含Statement語句, 而不能包含函數聲明這樣的源元素。另一方面,仔細看一看規則也會發現,唯一可能讓表達式出現在Block(塊)中情形,就是讓它作為表達式語句的一部分。但是,規范明確規定了表達式語句不能以關鍵字function開頭。而這實際上就是說,函數表達式同樣也不能出現在Statement語句或Block(塊)中(因為Block(塊)就是由Statement語句構成的)。

 

下面簡單說說函數聲明與函數表達式的異同。聲明和表達式的行為存在着十分微妙而又十分重要的差別。

  首先,函數聲明會在任何表達式被解析和求值之前先行被解析和求值。即使聲明位於源代碼中的最后一行,它也會先於同一作用域中位於最前面的表達式被求值。還是看個例子更容易理解。在下面這個例子中,函數 fn 是在 alert 后面聲明的。但是,在alert 執行的時候,fn已經有定義了:

alert(fn()); //輸出Helloworld!  
 
function fn() {
return 'Helloworld!';
}
簡單總結,區別在什么地方呢?

1. 聲明總是在作用域開始時先行解析;
2. 表達式在遇到時候才運算。

函數聲明還有另外一個重要的特點,即通過條件語句控制函數聲明的行為並未標准化,因此不同環境下可能會得到不同的結果。即是:
// 千萬不要這樣做! // 不同瀏覽器會有不同返回結果,
 
if (true) { function foo() { return 'first'; } } else { function foo() { return 'second'; } } foo(); // 記住,這種情況下要使用函數表達式:
var foo; if (true) { foo = function() { return 'first'; }; } else { foo = function() { return 'second'; }; } foo();

由於存在上述限制,只要函數出現在塊中(像上面例子中那樣),實際上就應該將其看作一個語法錯誤,而不是什么函數聲明或表達式。

  

  那么我們應該在什么時候使用函數聲明或函數表達式呢?函數聲明只能出現在“程序代碼”中,意味着只能在其它函數體中或者全局空間;它們的定義不能不能賦值給一個變量或屬性,或者作為一個參數傳遞出現在函數調用中;下面的例子是函數聲明的允許的用法,foo(),bar()和local()都是通過函數聲明模式聲明:

// 全局環境
function foo() {}
 
function local() {
// 局部環境
    function bar() {}
        return bar;
}

當你在語法上不能使用函數聲明的時候,你就可以使用函數表達式。比如:傳遞一個函數作為參數或者在對象字面量中定義一個函數:

// 這是一個匿名函數表達式
callMe(function () {
 
//傳遞一個函數作為參數
});
 
// 這是一個具名函數表達式
callMe(function me() {
 
// 傳遞一個函數作為參數,函數名為me
});
 
// 其他函數表達式
var myobject = {
    say: function () {
 
// I am a function expression
}
};

 

 
       


免責聲明!

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



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