javascript函数作用域和异常处理

函数作用域和异常处理

函数

  • 语法:

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

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

函数表达式

  • 使用表达式来定义函数,表达式中的函数名可以省略,如果这个函数名不省略,也只能用在此函数内部。
// 匿名函数
const add = function (x,y) {
    return x+y;
};
console.log(add(4,6));

//有名字的函数表达式
const sum = function _sum(x){
    if (x === 1) return x;
    return x+_sum(--x); //_sum只能内部使用
};
console.log(sub(5));

fun_001

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

  • 函数和匿名函数,本质上都是一样的,都是函数对象,只不过函数有自己的标识符–函数名,匿名函数需要借助其他的标识符。
  • 区别在于,函数会声明提升,函数表达式不会。
console.log(add(4,5));
//函数
function add (x,y){ //add会做声明提升,所有上面的add可以调用
    return x+y;
}

// console.log(sub(5,6));//sub未定义
// 有名字的函数表达式
var sub = function (x,y){
    return x-y;
};
console.log(sub(5,3))

高阶函数

  • 高阶函数:函数作为参数或返回值是一个函数的函数
  1. 完成一个计数器counter

    const counter = function(n=0){
        let c = n;
        return function(){
            return ++c;
        }
    }
    
    const c = counter()
    console.log(c())
    console.log(c())
    console.log(c())
    

    fun_002

    • 生成器版本计数器
    const counter = function * (n=0){
        let c = n;
        while (1){
            yield c++ //只能使用c++,不支持++c
        }
    }
    
    c = counter(3)
    console.log(c.next());
    console.log(c.next().value);
    console.log(c.next().value);
    console.log(c.next().value);
    

    fun_004

  2. 练习:完成一个map函数:可以对某一个数组的元素镜像某种处理

    const map = function(arr,fn){
        let newarr = [];
        for (let i of arr){
            newarr.push(fn(i));
        };
        return newarr;
    }
    
    arr = [1,2,3,4,5]
    console.log(map(arr,function(x){return x++})) //[ 1, 2, 3, 4, 5 ]
    console.log("- ".repeat(20))
    console.log(map(arr,function(x){return --x})) //[ 0, 1, 2, 3, 4 ]
    console.log("- ".repeat(20))
    console.log(map(arr,function(x){return x+1})) //[ 2, 3, 4, 5, 6 ]
    console.log("- ".repeat(20))
    console.log(map(arr,function(x){return x+=1})) //[ 2, 3, 4, 5, 6 ]
    

    fun_003

箭头函数

  • 箭头函数就是匿名函数,它是一种更加精简的格式。
  • 箭头函数的参数
    1. 如果一个函数没有参数,使用()
    2. 如果只有一个参数,参数列表可以省略小括号()
    3. 多个参数不能省略小括号,且使用逗号间隔
  • 箭头函数的返回值
    1. 如果函数体部分有多行,就需要使用(),如果有返回值使用return。
    2. 如果只有一行语句,可以同时省略大括号和return.
    3. 只要有return语句,就不能省略大括号。console.log(map([1,2,3,4],x => {return ++x})),有return必须有大括号。
    4. 如果只有一条非return语句,加上大括号,函数就成了无返回值了,例如console.log(map([1,2,3,4],x => {x*2}));加上了大括号,它不等价于x => {return x*2}
    5. 箭头函数不支持生成器
  1. 使用箭头函数完成上面的map函数的调用
const map = (arr,fn) => {
    let newarr = [];
    for (let i of arr){
        newarr.push(fn(i));
    };
    return newarr;
}

arr = [1,2,3,4,5]
console.log(map(arr,x => x++)) //[ 1, 2, 3, 4, 5 ]
console.log("- ".repeat(20))
console.log(map(arr,(x) => {return --x})) //[ 0, 1, 2, 3, 4 ]
console.log("- ".repeat(20))
console.log(map(arr,x => x+1)) //[ 2, 3, 4, 5, 6 ]
console.log("- ".repeat(20))
console.log(map(arr,x => x+=1 )) //[ 2, 3, 4, 5, 6 ]

fun_005

函数参数

普通参数

  • 一个参数占一个位置,支持默认参数
  • 注意
    1. js中没有Python中的关键字传参。
    2. js只是做参数位置的对应
    3. js并不限制默认参数的位置
  1. 示例

    const add = (x,y) => x+y;
    console.log(add(4,5));  //9
    
    //缺省值
    const add1 = (x,y=5) => x + y;
    console.log(add1(4,7));  //11
    console.log(add1(4));  //9
    

    fun_006

  2. 示例

    const add2 = (x=6,y) => x+y;
    console.log(add2())
    console.log(add2(1))
    console.log(add2(y=2,z=3)) //可以第一个参数的值是y=2这个表达式的值,也就是等号右边的值,即2.同理Z=3表达式的值是3,等价于add2(2,3)
    

    fun_007

  • add2()相当于add(6,undefined)
  • add2(1)相当于add(1,undefined)
  • add2(y=2,z=3)相当于add2(2,3)。
    1. 因为js没有关键字传参,而表达式由表达式的值
    2. 第一个参数的值是y=2这个表达式的值,也就是等号右边的值,即2。
    3. 同理z=3表达式的值是3。

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

  • js使用…表示可变参数(python用*收集多个参数)
const sum = function(...args){
    let result = 0;
    console.log(args) //会将参数收集成一个数组
    for (let x in args){
        result += args[x]
    }
    return result
}
console.log(sum(3,6,9))

fun_008

  • arguments对象
    1. 函数的所有参数会被保存在一个arguments的键值对对象中。
    2. ES6之前,arguments是唯一可变参数的实现。
    3. ES6开始,不推荐,建议使用可变参数。为了兼容而保留。
(function(x,...args){
    console.log(args);//苏州
    console.log(x);
    console.log("- ".repeat(20));
    console.log(typeof arguments);
    console.log(arguments);//不是传入的值
    for (let x of arguments) // 该对象可以使用of遍历
    {
        console.log(x);
    }
})(...[1,2,3,4,5])

fun_010

  • 注意:使用箭头函数,取到的arguments不是我们想要的
((x,...args) => {
    console.log(args);//苏州
    console.log(x);
    console.log(arguments);//不是传入的值
})(...[1,2,3,4,5])

fun_009

参数解构

  • 和Python类似,js提供了参数解构,依然使用了…符号来解构
const add = (x,y) => {console.log(x,y);return x+y;};
console.log(add(...[100,200]));
console.log('- '.repeat(20));

console.log(add(...[100,200,300,3,5,3]));
console.log('- '.repeat(20));

console.log(add(...[100]));
console.log('- '.repeat(20));

fun_011

函数的返回值

  • python中使用return 1,2返回值,本质上会封装成一个元组返回。
  • js中使用return 1,2返回值,是将1,2看做是逗号表达式,而表达式在js中是有自己的值。即1,2表达式中的值取决于最后一个逗号后面的表达式的值,即2
  1. 表达式的值
    • 类C的语言,都有一个概念----表达式的值,java,js
    • 赋值表达式的值:等号右边的值。
    • 逗号表达式的值:类c语言,都支持逗号表达式,逗号表达式的值,就是最后一个表达式的值。
a = (x=5,y=6,true);
console.log(a);

b = (123,true,z='test');
console.log(b);

function c(){
    return x=5,y=6,true,'ok';
}
console.log(c())
  • 所以,js的函数返回值依然是单值

fun_012

函数的作用域

  • function是函数的定义,是一个独立的作用域,其中定义的变量在函数外不可见。
    1. var a = 100可以提升声明,也可以突破非函数的块作用域。
    2. a = 100隐试声明不能提升声明,在"严格模式"下会出错,但是可以把变量隐试声明未全局变量。建议少用。
    3. let a = 100不能提升声明,而且不能突破任何的块作用域。推荐使用。
//函数中变量的作用域
function test(){
    a = 100;
    var b = 200;
    let c = 300;
};
//先运行test函数
test();

console.log(a);
// console.log(b);// 不可见
// console.log(c);//不可见

fun_013

user strict严格模式

  • 在js文件顶部,写上字符串"use strict"那么该js文件会按照严格模式执行。
    1. 严格模式中不使用隐试声明变量。变量不事先声明,无法使用。
"use strict"

a = 'abc'
console.log(a) // 打印出错,变量必须事先声明。

异常

抛出异常

  • 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 () => {}; //可以抛出一个函数对象

捕获异常

  • try...catch语句捕获异常。
  • try...catch...finally语句捕获异常,finally保证最终一定执行。

注意:这里的catch不支持类型,也就是说至多一个catch语句。可以在catch的语句块内,自行处理异常。

try{
    // throw new Error("new error");
    // throw new ReferenceError("Ref Error");
    // throw 1;
    // throw new Number(100);
    // throw [1,2,3];
    // throw {'a':1};
    throw () =>{};//函数
}catch (error){
    console.log(error);
    console.log(typeof error);
    console.log(error());
    console.log(error.constructor.name)
}finally{
    console.log("===end=======")
}

fun_014

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值