65ES6_函數

 

 

目錄

語法:... 1

函數:... 1

函數參數:... 2

函數參數-普通參數:... 2

函數參數-可變參數,rest parameters剩餘參數:... 3

arguments對象:... 3

參數解構:... 5

函數返回值:... 5

作用域:... 7

函數表達式:... 9

函數、匿名函數、函數表達式的差異:... 10

高階函數:... 11

箭頭函數:... 13

 

 

 

語法:

 

函數:

 

function 函數名(參數列表) {

         函數體;

         return 返回值;

}

 

例:

function add(x,y) {   //沒有邏輯

    return x+y;

}

console.log(add(4,5));   //函數調用

 

 

函數參數:

函數參數-普通參數:

一個參數佔一個位置,支持默認參數;

js中沒有py中的關鍵字傳參,即缺省值不用像py那樣往後放,建議默認參數寫到後面

js中只是作位置參數的對應;

js不限制位置參數的位置;

 

注:CC++java都是這樣;

 

例:

const add = (x,y) => x+y;

const add1 = (x,y=6) => x+y;

const add2 = (x=8,y) => x+y;   //js中缺省值不用像py那樣往後放(js中沒有py中的關鍵字傳參),建議像py那樣默認參數寫到後面;js只是作位置參數的對應;js不限制默認參數的位置;

console.log(add(4,5));

console.log(add(y=3,x=2));

console.log(add(aaa=1,bbb=2));   //V,相當於add(1,2)js中沒有關鍵字傳參,但是它的賦值表達式有值,aaa=1就是1

console.log(add());   //NaN,相當於add(undefined,undefined)

console.log(add1(4));   //相當於add(4,undefined)

console.log(add1(y=5,x=6));

console.log(add1());   //NaN,相當於add(undefined,6)

console.log(add2(2,2));

 

console.log(add(a1=5,(a2=6,a3=5)));   //括號中表達式值爲5

輸出:

9

5

3

NaN

10

11

NaN

4

10

 

 

 

函數參數-可變參數,rest parameters剩餘參數:

...表示可變參數,py中用*收集多個參數;

 

例:

const add = function (...args) {

    result = 0;

    for (let i in args) {

        result += args[i];

    }

    return result;

}

 

const sum = (...args) => args;

 

console.log(add(3,6,9));

console.log(sum(2,4,6));

 

let arr = [1,2,3,4,5];

console.log(add(arr));   //X,這樣返回的是字符串

console.log(typeof(add(arr)));

console.log(add(...arr));   //V,將arr解構

 

輸出:

18

[ 2, 4, 6 ]

01,2,3,4,5

string

15

 

 

 

arguments對象:

函數的所有參數會被保存在arguments的鍵值對字典對象中,py中的dict對應js中的對象;

ES6之前,arguments是唯一可變參數的實現;

ES6開始,不推薦,建議使用可變參數,arguements只是爲兼容而保留;

 

例:

(function (p1, ...args) {   //簡寫,函數定義+調用

    console.log(p1);

    console.log(args);

    console.log(arguments);

    for (let i of arguments)

        console.log(i);

}) ('abc',1,3,5)

輸出:

abc

[ 1, 3, 5 ]

{ '0': 'abc', '1': 1, '2': 3, '3': 5 }

abc

1

3

5

 

 

例:

((x,...args) => {   //簡寫,函數定義+調用

    console.log(args);

    console.log(x);

    console.log(arguments);

}) (...[2,4,6,8,10])

輸出:

[ 4, 6, 8, 10 ]

2

{ '0': {},

  '1':

   { [Function: require]

     resolve: { [Function: resolve] paths: [Function: paths] },

     main:

      Module {

        id: '.',

        exports: {},

        parent: null,

        filename: 'e:\\git_practice\\js\\node_833b816d371f0.tmp',

        loaded: false,

        children: [],

        paths: [Array] },

     extensions: { '.js': [Function], '.json': [Function], '.node': [Function] },

     cache: { 'e:\git_practice\js\node_833b816d371f0.tmp': [Object] } },

  '2':

   Module {

     id: '.',

     exports: {},

     parent: null,

     filename: 'e:\\git_practice\\js\\node_833b816d371f0.tmp',

     loaded: false,

     children: [],

     paths:

      [ 'e:\\git_practice\\js\\node_modules',

        'e:\\git_practice\\node_modules',

        'e:\\node_modules' ] },

  '3': 'e:\\git_practice\\js\\node_833b816d371f0.tmp',

  '4': 'e:\\git_practice\\js' }

 

 

 

參數解構:

py類似,使用...來解構;

另,js的參數解構,不需要解構後的值的個數和參數個數對應;

 

例:

const add = (x,y) => {console.log(x,y); return x+y};

 

console.log(add(...[1,2]));

console.log(add(...[1,2,3,4,5]));

console.log(add(...[100]));

輸出:

1 2

3

1 2

3

100 undefined

NaN

 

 

 

函數返回值:

C的語言,都有一個概念——表達式的值,類C語言都支持逗號表達式的值;

賦值表達式的值,是等號右邊的值;

逗號表達式的值,是最後一個表達式的值;

js的函數返回值即使寫的是多個,實際依然是單值;

另,py中,return 1,2,實質是返回一個tuple

高級語言,基本都是多個入一個出;

 

例:

const add = (x,y) => {return x,y};

console.log(add(4,100));

輸出:

100

 

例:

const add = (x,y) => {return x,y};

 

res = add(4.0,50);

console.log(res,typeof(res));

 

b = (x=5,y=6,true);

console.log(b);

 

a = (123,true,z='test');

console.log(a);

 

function c() {

    return x=5,y=6,true,'ok'

}

console.log(c());

輸出:

50 'number'

true

test

ok

 

 

例:

function a(obj) {   //實際應用中,用來解決傳參問題

    obj.x = 5;

    return obj;

}

 

var o = {

    x:100

}

 

console.log(a(o));

console.log(a(o).x);

輸出:

{ x: 5 }

5

 

 

 

 

作用域:

函數內定義的變量在函數外不可見;

var b = 200;,可提升聲明,也可突破非函數的塊作用域;

a = 100;,隱式聲明不能提升聲明,在嚴格模式下會報錯,但可把變量隱式聲明爲全局變量,建議少用;

let c = 300;,不能提升聲明,且不能突破任何塊作用域,推薦使用;

 

例,函數中變量的作用域:

function test() {

    a = 100;

    var b = 200;

    let c = 300;

}

 

// console.log(a);

// console.log(b);

// console.log(c);   //a,b,c均不可見

test();

console.log(a);   //函數在調用後纔會把a放到全局中

 

例,塊作用域中變量的作用域:

"use strict";   //嚴格模式,此模式開啓後,a = 100;不被允許;此句要麼在文件首行,要麼在函數首行

 

if (1) {

    // a = 100;   //X

    var b = 200;

    let c = 300;

}

 

// console.log(a);

console.log(b);

// console.log(c);   //不可見

 

例:

function show(i,arg) {

    console.log(i,arg);

}

 

x = 500;

 

function fn() {

    let z = 400;

    {

        var o = 100;

        show(1,x);

        t = 'free';   //嚴格模式下會報錯

        let p = 200;

    }

    var y = 300;

    show(2,z);

    show(3,x);

    show(4,o);

    show(5,t);

    // show(6,p);   //let不能突破塊作用域

    {

        show(7,y);

        show(8,o);

        show(9,t);

        {

            show(10,o);

            show(11,t);

            show(12,z);

        }

    }

}

 

fn();

// show(13,y);

show(14,t);   //global,不要這樣用

// show(15,o)   //y,o函數外不可見

show(16,z);   //var聲明提升,此時還沒有賦值

var z = 10;

 

const m = 2;

// m = 3;   //常量不可以重新賦值

輸出:

1 500

2 400

3 500

4 100

5 'free'

7 300

8 100

9 'free'

10 100

11 'free'

12 400

14 'free'

16 undefined

 

 

 

 

函數表達式:

使用表達式來定義函數,表達式中的函數可以省略,如果這個函數名不省略,也只能用在此函數內部;

 

例,有名字的函數表達式:

const add = function _add(x,y) {   //定義函數和常量時常用const,之後不可改;_add只能用在該函數內部

    console.log(_add);

    console.log(add);

    return x+y;

};   //表達式後要有分號

 

console.log(add(4,5));

// console.log(_add(4,5));   //X

輸出:

[Function: _add]

[Function: _add]

9

 

 

例,有名字的函數表達式:

const add = function fn(x,y) {   //fn只能用在該函數內部

    return x-y;

};

 

console.log(add(4,5));

// console.log(fn(4,5));   //X

 

 

例,匿名函數:

const add = function(x,y) {

    console.log(add);

    return x+y;

};

 

console.log(add(4,5));

 

例,遞歸:

const sum = function _sum(n) {

    let result = 0;

    if (n==1) return 1;

    return result += n + _sum(--n);

};

console.log(sum(5));

輸出:

15

 

 

 

函數、匿名函數、函數表達式的差異:

函數 VS 匿名函數,本質上都一樣,都是函數對象(變量指向一個函數對象),只不過函數有自己的標識符——函數名,匿名函數需要藉助其它的標識符而已;

(函數、匿名函數) VS 函數表達式,區別在於:函數會聲明提升(即調用可在聲明之前),函數表達式不會(即調用必須在聲明之後)

 

一般用,都是先聲明再調用;

 

例:

console.log(show);   //V,函數會聲明提升

console.log(add);   //X,函數表達式不會聲明提升,即,const add不會上移,必須先聲明再調用

 

const add = function(x,y) {

    return x+y;

};

 

function show() {

    console.log(add);

}

 

 

高階函數:

函數作爲參數,或返回一個函數;

 

例:

function a() {

    console.log('a func');

    return function b() {

        console.log('b func');

    };

}

 

let func = a();   //返回值指向b函數的定義

func();

輸出:

a func

b func

 

 

例:

function b() {

    console.log('b func');

}

 

function a(fn) {

    console.log('a func');

    return fn;

}

 

let func = a(b);

func();

輸出:

a func

b func

 

 

例,計數器:

let counter = function() {

    let i = 0;

   

    // function inc() {   //方式1

    //     return ++i;

    // }

    // return inc;

 

    // return function() {   //方式2,內部用不需要函數名

    //     return ++i;

    // }

 

    return () => ++i;   //方式3,箭頭函數

}

 

 

const c = counter();

console.log(c());

console.log(c());

console.log(c());

輸出:

1

2

3

 

 

例,map函數:

function map(fn,arr) {

    let newarr = [];

    for (i in arr) {

        newarr[i] = fn(arr[i]);

    }

    return newarr;

}

 

// let newarr = map(function (x) {return ++x}, [1,2,3,4,5]);   //方式1

// let newarr = map((x) => {return ++x}, [1,2,3,4,5]);   //方式2,若只留返回值(正確爲++x),必須把{}return一起脫掉,若爲{++x}則沒有返回值,返回的是[ undefined, undefined, undefined, undefined, undefined ]

let newarr = map((x) => ++x, [1,2,3,4,5]);   //方式3

console.log(newarr);

輸出:

[ 2, 3, 4, 5, 6 ]

 

 

例,map函數,生成器實現:

var map = function* (fn,arr) {   //生成器函數

    for (i in arr)

        yield fn(arr[i]);

};

 

let newarr = map(x => ++x, [1,2,3,4,5]);   //生成器對象

for (i of newarr)   //迭代

    console.log(i);

輸出:

2

3

4

5

6

 

 

 

箭頭函數:

是匿名函數,是一種更加精簡的格式;

let newarr = map(x => ++x, [1,2,3,4,5]);   //++xreturn的值

 

箭頭函數參數:

如果一個函數沒有參數,使用()

如果只有一個參數,參數列表可省略小括號;

多個參數不能省略小括號,且使用逗號間隔;

 

箭頭函數返回值:

若函數體部分有多行,就要用{},如果有返回值使用return

若只有一行語句,可同時省略{}return

若只一條return語句,不能省略大括號,即有return關鍵字必須要有{},如let newarr = map(x => {return ++x},[1,2,3,4,5]);

若只一條非return語句,加上{}則無返回值;

因此,記住最簡形式x => x+2即可;

 

 

注:

windows.alert()   //彈窗,browser對象,是全局對象,而js代碼中的全局對象是在nodejs上;彈窗測試時用,現都用遮罩層

browser新版本支持生成器、箭頭函數;

() => {},最簡單的箭頭函數,返回undefined

 

 

 

 

 

 

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章