1. 程式人生 > >懵逼的JavaScript大白(三)——函式

懵逼的JavaScript大白(三)——函式

一、宣告方式

1、函式宣告語句

function fun () {}

2、函式表示式

var fun = function () {};

3、建構函式建立方式(以後不會使用這種方式)

var fun = new Function('x', 'y','console.log(x, y);');
fun(100, 200);

二、屬性

1、length屬性:用於獲取形參個數

function fun (x, y, z) {}
console.log(fun.length);

在這裡插入圖片描述
2、caller屬性:用於獲取函式的呼叫位置
全域性中呼叫時,返回null
某個函式中呼叫時,返回這個函式fun2的函式體。

function fun () {
	console.log(fun.caller);
}
function fun2 () {
	fun();	
}
fun2();

在這裡插入圖片描述
3、prototype屬性:只有建構函式才使用這個屬性
4、arguments屬性:這個屬性已經不推薦使用了,而是推薦使用函式內的arguments偽陣列物件

function fun () {
	console.log(arguments);
	console.log(fun.arguments);
}
fun(100, 200, 300);

在這裡插入圖片描述

① arguments物件
偽陣列結構:具有索引和長度,沒有陣列方法
作用:用於獲取函式本次呼叫時傳入的所有實參

function fun () {
	console.log(arguments);
}
fun();

② arguments.callee屬性:用於獲取當前函式

function fun () {
	console.log(arguments.callee);
}
fun();

在這裡插入圖片描述

三、方法

① call() - 用於呼叫函式,同時可以修改函式內的this
② apply() - 用於呼叫函式,同時可以修改函式內的this
引數1:用於設定當前函式本次呼叫時的this值
引數2:陣列結構,用於儲存所有要傳入的實參

function fun (n, m) {
   	console.log(this);
    console.log(n, m);
}
 fun(100, 200);
 fun.call({name : 'jack'}, 'abc', 'efg');
 fun.apply({name : 'rose'}, ['引數1', '引數2']);

在這裡插入圖片描述
③ bind() - 用於繫結函式副本中的this和某些實參
引數1:用於繫結函式副本中的this,並且不可修改
後續引數:用於繫結函式副本中的某些實參
如果在函式副本中傳入實參表示設定繫結的實參後續的其他實參。
返回值:當前函式的副本

		function fun (num1, num2, num3) {
			console.log(num1, num2, num3)
		}
		// 傳入null,this預設為window
		var result = fun.bind(null, 100, 300);
		result();
		result(900);

在這裡插入圖片描述

四、使用方式

1、 普通使用方式: 函式宣告語句,函式表示式

① 預解析階段的提升方式不同。
② 在特殊場景中使用時,不同的形式在不同的瀏覽器中效果有所不同

2、 立即執行函式(自呼叫函式)

① 內部可以使用匿名函式或命名函式,但是通常使用匿名函式。
② 語法形式:(function () {})();
③ 使用方式:每個獨立功能外面包裹一個立即執行函式即可。還需要設定兩個引數,window,document,固定用法
④ 作用

 1. 減少全域性變數的使用
 2. 減少作用域的訪問次數
 3. 進行模組化操作

3、 回撥函式(將函式作為引數使用)

① 含義:將函式作為引數使用
② 使用場景:當某個函式中的功能程式碼不確定時可以使用函式引數(包裹)

4、 將函式作為返回值使用(用於解決閉包的問題)

閉包概念:一個可以對私有變數進行操作的函式稱為閉包函式
使用的好處:實現資料的私有化,增強資料的安全性。由於對私有變數進行操作的方式是我們提前設定的,所以使用者無法進行任意修改。
注意:不要濫用閉包函式。
普通的函式每次呼叫時不相關聯的,當某個函式呼叫完畢後,作用域會被銷燬,內部的變數和函式都被銷燬。當我們使用閉包函式時,由於私有變數可以被外界進行持續操作,這個私有變數在函式呼叫完畢也不會進行銷燬。

		var arr1 = [1, 2], arr3 = [3, 4], arr4 = [5, 6];
		function fun () {
			// sum是一個私有變數,無法被外界直接操作
			var sum = 0;
			// 在fun內部指定一種對sum這個私有變數的操作方式
			// 對某個陣列進行求和,並且將所有的和累計在sum中
			return function (arr) {
				for (var i = 0; i < arr.length; i++) {
					sum += arr[i];
				}
				console.log(sum);
			};
		}
		// 呼叫fun,接收閉包函式,命名為getSum,通過對getSum的使用,將每個陣列的和累計在私有變數sum中
		// 確保了資料的安全
		var getSum = fun();
		getSum(arr1);//3
		getSum(arr3);//10
		getSum(arr4);//21

5、遞迴函式

1 基本概念:函式內呼叫當前函式
2 遞迴可能出現的問題:
① 無限的呼叫(死迴圈)
② 執行的效率問題
3 解決方式:給遞迴函式設定結束條件
① 計數法:使用較少,因為for迴圈更簡單
② 根據功能的規律設定結束條件

		//斐波那契數列:1 1 2 3 5 8 13 21 34 55 89 144
		function getFb (n) {
			if (n === 1 || n === 2) {
				return 1;
			}
			return getFb(n - 1) + getFb(n - 2);
		}
		console.log(getFb(12));

③ 執行效率問題:由於遞迴呼叫重複執行,可能會導致某些值進行多次的重複計算,而這些重複計算是沒有意義的

		var obj = {};
		function getFb (n) {
			if (n === 1 || n === 2) {
				return 1;
			}
			return obj[n] ? obj[n] : obj[n] = getFb(n - 1) + getFb(n - 2);
		}
		console.log(getFb(12));