1. 程式人生 > >JS筆記:函數

JS筆記:函數

als 有變 循環 發生 init iss gif initial 匿名函數

一、定義與調用

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;
    
for (var i of rest) result += i; return result; };
View Code

二、變量作用域

若內部變量名與外部變量名重名,優先使用內部變量。

不在任何函數內定義的變量具有全局作用域,如window對象。

調用擁有全局作用域的變量中的函數不需要顯示指明對象,如window.alert函數。

使用var無法定義具有塊級作用域(例如循環)的變量,為此JS引入了let與const。

技術分享圖片
function f() {
    let result = 0;
    for (let i = 0; i < arguments.length; i++)
        result 
+= arguments[i]; return result; }
View Code

三、解析賦值

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: 
‘Stephen Curry‘, information: { team: ‘Golden State Warriors‘, number: 30, position: ‘Point Guard‘ } }; let {name, information: {team, number}} = Player; alert(name + team + number);
View Code

四、對象方法

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());//輸出World
View Code

JS筆記:函數