JS筆記:函數
一、定義與調用
arguments為當前函數調用者傳入的所有參數。由於JS的函數可以接受任意數量的參數,我們可以利用arguments來獲取所有參數。
ES6引入了rest參數,便於我們可以直接獲取未定義但是被傳入的參數。
function f1(arg) { var result = 0; for (var i = 1; i < arguments.length; i++) result += arguments[i]; return result; } var f2 = function (arg, ...rest) { var result = 0;View Codefor (var i of rest) result += i; return result; };
二、變量作用域
若內部變量名與外部變量名重名,優先使用內部變量。
不在任何函數內定義的變量具有全局作用域,如window對象。
調用擁有全局作用域的變量中的函數不需要顯示指明對象,如window.alert函數。
使用var無法定義具有塊級作用域(例如循環)的變量,為此JS引入了let與const。
function f() { let result = 0; for (let i = 0; i < arguments.length; i++) resultView Code+= arguments[i]; return result; }
三、解析賦值
ES6之後JS引入了解析賦值,可以同時對一組變量進行賦值。
//傳統寫法 const arr = [‘Hello‘, ‘JS‘, ‘ES6‘]; let str1 = arr[0]; let str2 = arr[1]; let str3 = arr[2]; //解析賦值 let [strA, strB, strC] = [‘Hello‘, ‘JS‘, ‘ES6‘];View Code
解析賦值也可用於快速從對象中獲取變量。
let Player = { name:View Code‘Stephen Curry‘, information: { team: ‘Golden State Warriors‘, number: 30, position: ‘Point Guard‘ } }; let {name, information: {team, number}} = Player; alert(name + team + number);
四、對象方法
this指針只有在顯式知名調用方法的對象時才指向對象本身,否則指向全局對象window。
在strict模式下函數中的strict指向undefined。該特性只是讓錯誤暴露,並未解決this的指向問題。
在獨立調用的函數中,若希望this指針指向對象而非window或undefined,則需要使用apply。
‘use strict‘; let Rectangle = { length: 10, height: 10, isSquare: function () { if (this === window || this === undefined) return false; else return this.length === this.height; } }; alert(Rectangle.isSquare());//true let lambda = Rectangle.isSquare; alert(lambda());//false alert(lambda.apply(Rectangle, []));//true(參數為空)View Code
五、高階函數
以其他函數作為參數的函數稱之為高階函數。
function f1(a, b, f) { return f(a) + f(b); } let f2 = Math.abs; let result = f1(-1, -3, f2); alert(result);View Code
通過調用數組對象的map方法可以產生指定映射的新數組。
調用reduce方法獲取對數組所有元素進行指定二元運算的結果。
調用filter方法將數組的特定元素過濾並返回剩余的元素。
調用sort方法將數組排序,需要註意的是sort方法會默認將所有的元素以字符串的形式進行排序,若希望以數字的形式進行排序,必須自定義比較規則。
let arr = [-1, -2, -3, -4, -5]; //map示例 let result = arr.map(Math.abs);//[1,2,3,4,5] //reduce示例 let f1 = function (a, b) { return a + b; }; let result1 = arr.reduce(f1);//-15 //filter示例 let f2 = function (x) { return x % 2 !== 0; }; let result2 = arr.filter(f2);//[-1,-3,-5] //sort示例 let f3 = function (a, b) { return a - b; }; let result3 = arr.sort(f3);//[-5,-4,-3,-2,-1]View Code
六、閉包
函數可以作為返回值,但是如果返回的函數引用了局部變量,該局部變量不應是任何後續會發生變化的,因為返回的函數會延後調用。
function f() { var arr = []; for (var i = 0; i < 3; i++) { arr.push(function () { return i; }); } return arr; } var arr = f(); var result = []; for (var i = 0; i < arr.length; i++) result[i] = arr[i](); alert(result);//[3,3,3]View Code
由於JS沒有類,所以需要借助閉包來封裝私有變量。簡單來說閉包就是攜帶狀態的函數,並且其狀態完全可以對外界隱藏。
function counter(initial) { let t = initial || 0; return { add: function () { t++; return t; } } } let arr = []; let c1 = counter(); for (let i = 0; i < 3; i++) arr[i] = c1.add(); alert(arr);//[0,1,2] let c2 = counter(10); for (let i = 0; i < 3; i++) arr[i] = c2.add(); alert(arr);//[10,11,12]View Code
七、箭頭函數
ES6加入了箭頭函數,相當於匿名函數。
箭頭函數與匿名函數的區別是,箭頭函數內部的this是詞法作用域,由上下文確定,修復了this的指向問題。
‘use strict‘; let obj1 = { information: ‘Hello‘, getInformation: function () { return function () { return this.information;//this指向window或undefined }; } }; let getInfo = obj1.getInformation(); alert(getInfo());//無法輸出 let obj2 = { description: ‘World‘, getDescription: function () { return () => this.description;//this指向obj } }; let getDesc = obj2.getDescription(); alert(getDesc());//輸出WorldView Code
JS筆記:函數