函式其實乙個封裝一段**的物件,之所以要封裝是為了便於我們以後**的重用。通俗的說就是一項任務可能被反覆的使用,就要定義函式,以便以後反覆使用。
函式宣告
定義:
使用function關鍵字宣告乙個函式,再指定乙個函式名,叫函式宣告。
表示式:
function 函式名(引數列表)
函式表示式function
add1
(n1,n2);
定義:
使用function關鍵字宣告乙個函式,但未給函式命名,最後將匿名函式賦予乙個變數,叫函式表示式,這是最常見的函式表示式語法形式。
表示式:
var 函式名=function (引數列表)
函式構造法var add2=function
(n1,n2);
定義:
使用new方法建立乙個函式,並傳參給函式,宣告乙個變數接收此函式(引數必須加引號)
表示式:
var 函式名=new function (「引數1」,「引數2」, ……;「函式體;return 返回值」}
三者的區別var add3=new
function
('n1','n2','return n1+n2');
console.log(sum3(2,3));//5
函式宣告和函式表示式不同之處在於:
解析器會先讀取函式宣告,並使其在執行任何**之前可以訪問;
而函式表示式則必須等到解析器執行到它所在的**行才會真正被解釋執行。
從技術角度講,函式構造法其實是乙個函式表示式。一般不推薦用這種方法定義函式,因為這種語法會導致解析兩次**(第一次是解析常規ecmascript**,第二次是解析傳入建構函式中的字串),從而影響效能。
出現這樣的原因,是因為函式宣告提前(function declaration hoisting),後面會講解宣告提前是什麼//函式宣告
fnname();
function
fnname
()//正常,因為『提公升'了函式宣告,函式呼叫可在函式宣告之前
//函式表示式
fnname();
var fnname=function
()//報錯,變數fnname還未儲存對函式的引用,函式呼叫必須在函式表示式之後
函式的原理
讓引擎按照函式的步驟執行任務
儲存:
函式名其實就是乙個普通的變數
函式本身是乙個引用型別的物件(儲存多個資料的複雜資料結構)
函式名通過函式的位址值,引用函式物件
強調: 宣告時,不會執行函式的內容。
呼叫:
1. window中宣告變數,準備儲存函式的返回值
2. 找到函式物件,建立函式執行時的臨時儲存空間
3. 將呼叫時傳入的引數值,放入臨時儲存空間的引數變數中
4. 執行函式體,修改臨時儲存空間中的變數值
5. 將返回值,返回window中,儲存到指定變數
6. 函式執行後,臨時儲存空間釋放!導致,函式內區域性變數一同釋放
所以: 函式中的引數變數和var的變數,只能在函式呼叫時,內部使用,出了函式,無法使用。
宣告提前
在開始執行程式前,引擎會首先查詢所有var宣告的變數和function宣告的函式,將他們集中到當前作用域的頂部優先建立
總結
強烈建議,所有要用到的變數集中宣告在當前作用域的頂部
es6:
盡量用let代替var
強調:
1. let必須在嚴格模式下使用!
2. let作為區域性變數時,必須放在**段開頭
區域性變數let之前的變數不可用
3. 用var 函式名=function() 代替function 函式名()
區別: function 函式名() 會被宣告提前
var 函式名=function() 不會被宣告提前
揭示了本質: 函式名其實就是乙個變數
函式名通過位址引用著函式物件
建立函式的方式和區別
函式宣告 function add a,b add 1,2 3存在函式提公升,在js中最先執行 函式表示式 命名函式 var add function a,b add 1,2 3不存在函式提公升,等到解析器解析到它時才會執行。因為這是乙個命名函式,js中有變數提公升和函式提公升,命名函式相當於把函式...
JS中建立函式的三種方式及區別
1.函式宣告 function sum1 n1,n2 2.函式表示式,又叫函式字面量 var sum2 function n1,n2 兩者的區別 解析器會先讀取函式宣告,並使其在執行任何 之前可以訪問 而函式表示式則必須等到解析器執行到它所在的 行才會真正被解釋執行。自執行函式嚴格來說也叫函式表示式...
函式呼叫方式總結
1 stdcall是pascal程式的預設呼叫方式,通常用於win32 api中,函式採用從右到左的壓棧方式,自己在退出時清空堆疊。vc將函式編譯後會在函式名前面加上下劃線字首,在函式名後加上 和引數的位元組數。2 c呼叫約定 即用 cdecl關鍵字說明 按從右至左的順序壓引數入棧,由呼叫者把引數彈...