初識函數

函數數據類型

定義函數的幾種方法

1、函數聲明(使用function語句來創建一個函數)

functiona,b){return a+b;};

2、函數表達式,又叫函數字面量

var fn=functiona,b){return a+b;};

這兩種方式的區別:解析器會先讀取函數聲明,並使其在執行任何代碼之前都可以被訪問,而函數表達式則需要解析器執行到他所在的代碼纔會被真正的解釋執行(主要原因js代碼的變量提升導致的,在變量提升是帶var和function關鍵字的執行分爲兩種情況了)

3、構造函數法

 function Person() {
 .......
  }
  var p1= new Person();

注意參數必須加引號

var sum3=new Function('n1','n2','return n1+n2');
console.log(sum3(2,3));
//輸出結果爲5

ps:從技術角度講,這是一個函數表達式。一般不推薦用這種方法定義函數,因爲這種語法會導致解析兩次代碼(第一次是解析常規ECMAScript代碼,第二次是解析傳入構造函數中的字符串),從而影響性能。

構造函數

1、普通函數

function Person() {
    }
    Person();

函數執行:preson不是類,他僅僅是一個普通的函數

2、 構造函數

function Person() {
 .....
  }
  var p1= new Person();
    console.log(p1);
  /*new Person()
1、把Person變成一個類:類都是函數數據類型的(包含內置類)
2、把Person當成一個普通的方法來執行
3、p1就是當前類的實例,實例都是對象數據類型的*/

Person函數(構造函數)執行過程

1.形成一個私有作用域
2.形參賦值和變量提升
3.(構造)瀏覽器會默認的在這個作用於中開闢一個堆內存(對象數據類型的值),然後把這個對象作爲函數執行的主體(this)這個對象就是當前這個類的一個實例
4.js代碼自上而下執行
5.(構造)即使我們不寫return,瀏覽器會默認返回一個結果,返回的結果就是第三步創建的那個對象。=>瀏覽器默認創建的實例返回
構造函數執行,此時的person不是一個普普通通的函數,而是一個自定義類,而接收到的返回結果就是當前這個類的一個實例。

一般情況下,構造函數的函數名爲大寫(規範情況下,當然也可以不大寫)

匿名函數

所謂的匿名函數就是沒有名字的函數,正是因爲其沒有名字所以我們也沒有辦法找到他們,就涉及到匿名函數的調用問題了

匿名函數之自執行函數:
函數的創建和執行一起完成了,自執行函數不在進行變量提升

;(function () {
    console.log('ok'); 
})();

~function () {}();
 !function () {}();
 +function () {}();
-function () {}();

在function前面加!、+、-、~都可以將函數聲明轉化爲函數表達式,消除了js引擎識別函數聲明和函數表達式的歧義,
加()是最安全的方法,免得其他的和函數返回值進行運算

不過這樣的寫法有什麼用呢?

答: javascript中沒用私有作用域的概念,如果在多人開發的項目上,你在全局或局部作用域中聲明瞭一些變量,可能會被其他人不小心用同名的變量給覆蓋掉,
根據javascript函數作用域鏈的特性,可以使用這種技術可以模仿一個私有作用域,用匿名函數作爲一個“容器”,
“容器”內部可以訪問外部的變量,而外部環境不能訪問“容器”內部的變量,
所以( function(){…} )()內部定義的變量不會和外部的變量發生衝突,俗稱“匿名包裹器”或“命名空間”

1、function {
函數體:我們把實現當前功能或者需要做事情的那些代碼,全部放在函數體中。
}
例如:

function sum(){
}
sum() ;//把上面的方法執行而且可以執行很多次

理解函數

函數就是一個方法或者一個功能使用它能夠做某些事情。例如我們可以把家裏的洗衣機理解爲函數,使用它可以洗衣服。
函數具有兩部分:創建函數(購買了一臺洗衣機)、執行函數(使用洗衣機洗衣服),只創建了但是沒有執行,函數沒有任何意義。
sum 指的是函數本身
sum(); 把函數執行,代表的是函數執行的結果。

創建函數

1.創建一個函數名
2.開闢一個新的內存空間(有16進制的地址),然後把函數體中實現功能的js代碼按照“字符串”的格式存儲在空間中(對象存儲的是屬性名和屬性值)
3.把空間地址賦值給函數名,此時函數名就可以和函數體本身關聯在一起。
函數創建不執行沒有意義的原因就是:創建的時候存儲的都是無意義的字符串。

函數執行

  1. 函數執行的時候會形成一個私有作用域(我的地盤我做主),保護裏面的私有變量不受外界干擾,我們把這種機制叫做“閉包”。提供一個環境供函數體中的代碼執行。
  2. 把創建的時候存儲的字符串變成真正的js代碼,在私有地盤自上而下執行。

函數的作用

(1)
1. 封裝
2. 低耦合,高內聚
3. 減少代碼的冗餘度,提高代碼的重複利用率
(2)
函數執行的時候會形成一個私有作用域(我的地盤我做主),保護裏面的私有變量不受外界干擾,我們把這種機制叫做“閉包”。

形參:當我們創建一個方法實現某個功能,但是實現該功能的原材料並不清楚,只有執行這個功能的時候,讓用戶傳遞過來才知道,此時我們可以先想像洗衣機一樣,提供一些入口->形參:函數的入口。

定義了形參,但是執行的時候沒有給傳遞值,形參默認存儲的值是undefined(100+undefined=NaN).

實參:`執行的時候給函數傳遞的值。
定義了形參,但是執行的時候沒有給傳遞值,形參默認存儲的值是undefined(100+undefined=NaN)

函數的三種角色

1、普通函數
私有作用域、形參賦值、變量提升、代碼執行、返回值、arguemnts、堆棧內存的銷燬問題、作用域鏈

2、
實例、類、instanceof、constructor、prototype、proto、原型鏈

3、普通對象
就把它當作一個普通的obj即可,有自己的屬性名和屬性值。
● name:函數名
● length:形參的個數
● prototype
proto
● …….
函數的三種角色之間沒有必要的聯繫。

函數中常用的三種方法:
call、 apply 、bind

屬於Function上定義的三中方法所有的函數數據類型值都可以調取這三中方法
作用:三種方法都是用來改變一個函數中的this關鍵字指向的(bind不兼容ie6-8)其餘的兼容所有的瀏覽器。

三種常用方法的語法:

>

① 把需要操作函數中的this變爲第一個實參值,(在非嚴格模式下),第一個實參爲空或者寫null或者undefined,this都是window,剩下的第一個實參是誰,this就是誰。
(嚴格模式下)第一個實參爲空,this是undefined,其餘的寫誰this就是誰。

② 改變爲this後,把需要操作的函數執行。
唯一的區別:call在給函數傳遞實參的時候是一個個傳遞的,而apply是放在一個數組中一起傳遞的(但是也相當於一個個傳參)

bind的語法和call一樣,但是作用不一樣,bind只是提前把函數中的this改變了,但是並沒有立即把函數執行,它屬於預先改變this(柯里理化思想)

定時器中的應用

   window.setInterval(fn,1000);//每隔一秒執行一次fn
    window.setInterval(fn(),1000);//創建一個定時器,每隔一秒中執行fn執行的返回結果
    window.setInterval(fn.call(obj2),1000);//創建定時器的時候就把fn執行了,雖然改變了this,但是一秒後執行的是fn返回的結果
    window.setInterval(fn.bind(obj2),1000);//創建定時器的時候,提前把fn中的this設置爲obj2,1秒後執行的是fn
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章