【重溫基礎】4.函式

pingan8787發表於2018-12-13

本文是 重溫基礎 系列文章的第四篇。今日感受:常懷感恩之心,對人對己。

系列目錄:

本章節複習的是JS中的基礎元件之一,函式,用來複用特定執行邏輯。

1.定義函式

定義函式有兩種方法:函式宣告函式表示式

1.1 函式宣告

也成為函式宣告,通常格式為:

function f (a){ 
return a + 1;

}複製程式碼

解釋:這裡宣告一個函式 f ,並傳入一個引數 a ,當函式執行以後,通過 return 關鍵字返回了 a+1的值。

引數
當傳入的引數是一個數字/字串等具體的值的時候,若引數的值被改變,不會影響到全域性或呼叫函式。
但如果引數是個物件,若函式內改變的這個引數的屬性,則函式外部的這個引數原始的值會被修改。

var leo = { 
age:20
}function f(obj){
obj.age = 15;
obj.name = 'leo';

}f(leo);
console.log(leo);
//{age: 15, name: "leo"
}
複製程式碼

1.2函式表示式

通過定義一個匿名的函式,來賦值給一個變數,通過這個變數來呼叫這個函式。

var f = function (a){ 
return a + 1;

}複製程式碼

但是函式表示式也可以提供函式名,用於函式內部呼叫,並指代本身,也可以作為偵錯程式堆疊跟蹤中識別該函式。

var f = function g(a){ 
return n <
2 ? 1 : a*g(a-1);

}複製程式碼

另外,函式表示式宣告可以用來根據不同條件,來定義一個函式:

var f;
if(a == 1){
f = function (){
return 'when a == 1';

}
}else {
f = function (){
return 'when a != 1';

}
}複製程式碼

2.函式呼叫

函式定義完成後不會自動執行,需要我們通過函式名稱來呼叫,才能真正執行:

var f = function (){ 
console.log('ok');

}f();
// 'ok'複製程式碼

另外,函式也可以呼叫自身,這就是遞迴過程:

function f (n){ 
if( n==0 || n==1) {
return 1;

}else {
return n * f(n-1);

}
}// 三目運算function f (n){
return (n==0 || n==1)?1: n*f(n-1);

}複製程式碼

3.函式作用域

由於函式只在函式的內部有定義,所以函式內部定義的變數在函式外部不能訪問,函式內部就是這個函式的作用域。
當一個父級函式內,還定義了一個子級函式,則這個子級函式可以訪問父級函式定義的變數。

// 全域性作用域 global scopevar a = 1, b = 2;
function f (){
return a + b;

}f();
// 3function g(){
var a1 = 'leo', b1 = 'pingan';
function hi (){
return a1 + '和' + b1
} return hi();

}g();
// 'leo和pingan'複製程式碼

3.1 閉包

閉包是 JavaScript 中最強大的特性之一,並且JS允許函式巢狀。
在一個函式內部在巢狀一個函式,而巢狀的這個函式對外面的函式是私有的,則形成一個閉包,閉包是一個可以自己擁有獨立的環境和變數的表示式,通常是函式。
理解一下,前面說的內部函式可以呼叫外部函式的變數和方法,那麼可以這麼理解:閉包的函式繼承了父級容器函式的引數和變數,即內部函式包含外部函式的作用域
總結一下:

  • 內部函式只能在外部函式中訪問;
  • 內部函式形成閉包:可以訪問外部函式的引數和變數,但外部函式卻不能使用這個內部函式的引數和變數;
function f(a) { 
function g(b){
return a + b;

} return g;

}var a1 = f(5);
// ƒ g(b){
return a + b;

}
var a2 = a1(6);
// 11var a3 = f(5)(6);
// 11複製程式碼

閉包可以給內部函式的變數提供一定的安全保障
另外,閉包還有複雜的用法:

var f = function (name){ 
var age ;
return {
setName : function (newName){
name = newName;

}, getName : function (){
return name;

}, getAge : function (){
return age;

}, setAge : function (newAge){
age = newAge;

}
}
}var leo = f('leo');
leo.setName('pingan');
leo.setAge(20);
leo.getName();
// 'pingan'leo.getAge();
// 20複製程式碼

3.2命名衝突

在同一個閉包作用域下若引數或變數名相同,產生衝突,則優先使用作用域最近

function f(){ 
var a = 1;
function g(a){
return a + 1;

} return g;

}f()(3);
// 4複製程式碼

4.arguments物件

函式的實際引數會被儲存在一個類陣列物件 arguments 物件中,通過索引訪問具體的引數:

var a = arguments[i]複製程式碼

arguments的索引從0開始,也有arguments.length屬性獲取長度。
當我們不知道引數的數量的時候,可以使用arguments.length來獲取實際傳入引數的數量,再用arguments物件來獲取每個引數。
例如:

// 拼接所有引數為一個字串// 引數 s 為分隔符function f( s ){ 
var text = '';
for(var i = 0;
i<
= arguments.length;
i++){
text += arguments[i] + s ;

} return text;

}f('--','leo','pingan','robin');
// "----leo--pingan--robin--undefined--"f('**','leo','pingan','robin');
// "****leo**pingan**robin**undefined**"複製程式碼

5.函式引數

ES6開始,新增兩個型別的引數:預設引數剩餘引數

5.1預設引數

若函式沒有傳入引數,則引數預設值為undefined,通常設定引數預設值是這樣做的:

// 沒有設定預設值function f(a, b){ 
b = b ? b : 1;
return a * b;

}f(2,3);
// 6f(2);
// 2// 設定預設值function f(a, b = 1){
return a * b;

}f(2,3);
// 6f(2);
// 2複製程式碼

5.2剩餘引數

可以將引數中不確定數量的參數列示成陣列,如下:

function f (a, ...b){ 
console.log(a, b);

}f(1,2,3,4);
// a =>
1 b =>
 
[2, 3, 4]
複製程式碼

6.箭頭函式

函式箭頭表示式是ES6新增的函式表示式的語法,也叫胖箭頭函式,變化:更簡潔的函式和this

  • 更簡潔的函式
// 有1個引數let f = v =>
v;
// 等同於let f = function (v){return v
};
// 有多個引數let f = (v, i) =>
{return v + i
};
// 等同於let f = function (v, i){return v + i
};
// 沒引數let f = () =>
1;
// 等同於let f = function (){return 1
};
let arr = [1,2,3,4];
arr.map(ele =>
ele + 1);
// [2, 3, 4, 5]複製程式碼
  • this注意這幾點:
    1. 箭頭函式內的this總是指向定義時所在的物件,而不是呼叫時。
    2. 箭頭函式不能當做建構函式,即不能用new命令,否則報錯。
    3. 箭頭函式不存在arguments物件,即不能使用,可以使用rest引數代替。
    4. 箭頭函式不能使用yield命令,即不能用作Generator函式。

一個簡單的例子:

function Person(){ 
this.age = 0;
setInterval(() =>
{
this.age++;

}, 1000);

}var p = new Person();
// 定時器一直在執行 p的值一直變化複製程式碼

參考資料

1.MDN 函式


本部分內容到這結束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 github.com/pingan8787/…
JS小冊 js.pingan8787.com

來源:https://juejin.im/post/5c127fb56fb9a049c643b8f9

相關文章