从无到有的学习JavaScript——第四篇(函数)

补充知识:Symbols类型

ES6提供了Symbol类型,内建原生类型

// symbol
let s = Symbol()  
console.log(s)

let s1 = Symbol()
console.log(s1)

console.log(s == s1)  // false,Synbol每次定义取的值都是不同的

let a = 1

let obj = {
    a,  // a是变量
    b: 'abc',  // b不是变量,是key
    //s:s  // 前面的s是key,不是变量,后面的s是变量
    // s  // s是变量
    [s]: 2000  // s是变量
}
console.log(obj)
// { a: 1, b: 'abc', [Symbol()]: 2000 }

for(let x in obj){
    console.log(x)  // 注意 [Symbol()]: 2000是访问不到的
    // a b
}

var color_obj = {
    red: 'rec',
    blue: 'blue',
    black: 'black',
    green: 'green'
}

const color = {
    red: Symbol(),
    blue: Symbol(),
    black: Symbol(),
    white: Symbol()
}

1.函数


function 函数名(参数列表){
    函数体;
    return 返回值;
}

function add(x, y){
    return x + y;
}
console.log(add(4, 5))  // 9

1.1 函数表达式

使用表达式来定义函数,表达式中的函数名可以省略,如果这个函数名不省略,也只能用在此内部。

// 匿名函数
const add = function(x, y){
    return x  + y
}
console.log(add(4, 5)) // 9

// 有名字的函数表达式
const sub = function fn(x, y){  // fn只能在此内部使用
    return x - y
}

console.log(fn(5, 1))  // 会报错,fn只能在定义的函数内部使用,就是说递归的时候使用

// 有名字的函数表达式,实现递归求和
const sum = function _sum(n){
    if (n == 1){
        return 1
    }
    return n + _sum(n - 1)  // n + _sum(--n) 也可以,但是不能写成_sum(--n) + n
}

console.log(sum(5))  // 15

函数、匿名函数、函数表达式的差异

函数和匿名函数本质是一样的,都是函数对象,只不过函数有自己的标识符——函数名,匿名函数需要借助其他标识符而已,而函数与函数表达式的区别在于,函数有声明提升,而函数表达式没有。

console.log(add(4, 6))  // 直接输出结果10

function add(x, y){  // 声明提升
    return x + y
}

console.log(sub(10, 1))  // 会报错,函数表达式没有声明提升

const sub = function(x, y){
    return x - y
}

1.2 高阶函数

高阶函数是函数作为其参数或者返回值为参数的函数。

完成一个计数器函数counter:

const counter = function(){
    let c = 0
    return function(){
        return ++c
    }
}

const c = counter()  // 返回一个函数对象
console.log(c())
console.log(c())
console.log(c())
console.log(c())
console.log(c())

完成map函数,实现对某一个数组的元素进行某种处理(如使数组中的每一个元素都加1),返回新的数组

const add = function(c){
    return c + 1
}

const map = function(arr, func){
    let new_arr = []
    for(let i = 0; i < arr.length; i++){
        new_arr[i] = func(arr[i])
    }
    return new_arr
}

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

1.3 箭头函数

箭头函数就是匿名函数,它是一种更加精简的格式。

箭头函数参数

  • 如果一个函数没有参数,使用()
  • 如果只有一个参数,参数列表可以省略小括号()
  • 多个参数不能省略小括号,且使用逗号间隔

箭头函数返回值:

  • 如果函数体部分有多行,就需要使用{},如果有返回值使用return;
  • 如果只有一语句,可以同时省略大括号和return;
  • 只要有return语句,就不能沈略大括号;
  • 如果只有一条非return语句,加上大括号,函数就成了无返回值的了。
const add = function(c){
    return c + 1
}

const map = function(arr, func){
    let new_arr = []
    for(let i = 0; i < arr.length; i++){
        new_arr[i] = func(arr[i])
    }
    return new_arr
}

console.log(map([1, 2, 3, 4], y => console.log(y)))
/*
1
2
3
4
[ undefined, undefined, undefined, undefined ]
*/
console.log(map([1, 2, 3, 4], y => {y}))
// [ undefined, undefined, undefined, undefined ]

 

2.函数参数

2.1 普通参数

一个参数占一个位置,支持默认参数

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

console.log(add(4, 5))

const sub = (x, y=5) => x - y

console.log(sub(9, 3))  // 6
console.log(sub(10))  // 5

const add2 = (x=10, y) => x + y

console.log(add())  // NaN
console.log(add(1))  // NaN
console.log(add(y=2, z=3))  // 5
// JS中没有关键字传参,只是做参数位置的对应,并不限制默认参数的位置,传的是赋值表达式的值
  1. JS中没有关键字传参,这与python是不同的
  2. JS中只是做参数位置的对应
  3. JS并不限制默认参数的位置,传入的参数是赋值表达式的值

建议:默认参数写到后面,这是一个好习惯

2.2 可变参数(rest parameters剩余参数)

JS中使用...表示 可变参数,(python使用*收集多个参数)

const sum = function(...args){
    let result = 0
    console.log(args)  // [ 3, 6, 9, 12 ]
    // args是数组,要解构的话使用...args
    for(let x in args){
        result += args[x]
    }
    return result
}

console.log(sum(3, 6, 9, 12))  // 30

arguments对象:

function fn(p, ...args){
    console.log(p)
    console.log(args)
    console.log('~~~~~~~~~~~~~~')
    console.log(arguments)  // 对象
    for(let x of arguments){  // 该对象可以使用of
        console.log(x)
    }
}

fn('abc', 1, 3, 4)
/*
abc
[ 1, 3, 4 ]
~~~~~~~~~~~~~~
[Arguments] { '0': 'abc', '1': 1, '2': 3, '3': 4 }
abc
1
3
4
*/

ES6之前,arguments是唯一可变参数的实现。ES6开始,不推荐,建议使用可变参数,为了兼容而保留。注意,使用箭头函数,取到的arguments不是我们想要的。

const f = (x, ...args) => {
    console.log(args)  // [ 2, 3, 4 ]
    console.log(x)  // 1
    console.log(arguments)  // 不是传入的值
}

f(...[1, 2, 3, 4])

参数解构:

和python类似,JS提供了 参数解构,依然使用..符号来解构。

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

console.log(add(...[10, 20]))
console.log(add(...[1, 2, 3, 4, 5]))  // 3
console.log(add(...[100]))  // NaN

JS支持参数解构,不需要解构后的值个数和参数个数对应。

3. 函数的返回值

python中可以使用,return 1, 2返回多个值,本质上就是一个值,就是一个元组。

const add = (x, y) => {return x, y}  //返回的是逗号表达式的值
console.log(add(4, 5))  // 5

表达式的值:类C的语言,都有一个概念--表达式的值;赋值表达式的值:等号右边的值;逗号表达式的值:就是最后一个表达式的值。JS的函数返回值依然是单值。严格模式:使用"use strict",这条语句放到函数的首行,或者js脚本的首行。

4. 异常

4.1 抛出异常

JS的异常语法与java相同,使用throw关键字抛出。使用throw关键字可以抛出任意对象的异常

throw new Error('new error');
throw new ReferenceError('Ref Error');
throw 1;
throw 'not ok'
throw [1, 2, 3]
throw {'a': 1};
throw () => {};  // 函数

 

4.2 捕获异常

try...catch语句捕获异常,finally保证最终一定执行。注意这里的catch不支持类型,也就是说至多一个catch语句,可以在catch语句块内,自行处理异常。

try{
    throw new Error('new error')
    // throw new ReferenceError('Ref Error')
}catch(error){
    console.log(error)
    console.log(typeof error)  // object
    console.log(error.constructor.name)  // Error
}finally{
    console.log('===========end===============')
}

 

你可能感兴趣的:(JavaScript)