函数、闭包总结

一、函数

函数:n条语句的封装体

  • 创建
  1. function 函数名(){} 声明函数:
    一经声明,全局调用(不在意书写位置)。
  2. var 函数名 = function(){} 函数表达式 :
    匿名函数若带上名字,名字失效。
  3. **构造函数 var 函数名 = new Function(参数, 语句) **不常用
  • 属性
    - name 函数的名字
    - length 返回函数的形参个数

  • 形参、实参
    - 形参个数 > 实参个数 多余的形参值是 undefined
    - 形参个数 < 实参个数 多余的实参在arguments里
    - arguments :所有实参的集合,是一个伪数组,常用于实现不定参函数
    - 非严格模式下 arguments.callee 是对函数的引用。严格模式不可用。

  • 简单类型值作为实参 、 引用类型作为实参的区别:
    1. 简单类型值作为参数,函数内部的变化不会影响到传入的变量
    2. 引用类型值作为参数,函数内部的变化会影响到传入的变量
    - 默认参 短路语句

  • 返回值
    - return 不写默认返回 undefined

  • 函数作用域
    - 内部可以使用外部函数或者window的变量
    - 函数外不能使用函数内部变量
    - 立即执行函数 (创建独立空间) 函数表达式的立即执行 3

  • 高级函数:将函数作为参数或者返回值的函数

    • 闭包:能够访问另一个函数作用域中变量的函数
  • 函数声明提升 > 变量的声明提升

1.不定参函数 arguments
 function add(){
    
    
            var count = 0;
            for(var i = 0; i < arguments.length; i ++){
    
    
                count += arguments[i];
            }
            return count;
        }

        var returnValue = add(1,2); // 3
2. ES6 不定参 (…args) 除已知参数外剩下的参数的集合
    // 剩余参数必须写在末尾
  function add2(a,b, ...args){
    
    
    console.log(args);
}
add2(1,2,3,4,5); //    [3,4,5]
3.默认参
  function mul(a, b){
    
    
            // 如果没有a, a = 2
            // 如果没有b, b = 3
            a = a || 2;
            b = b || 3;
            
            return a * b;
        }
        console.log(mul()); // 6
function mul1(a = 3, b = 2){
    
    
            console.log("默认参", a * b);
        }
        mul1(); // 6
        mul1(4); // 8
        mul1(undefined, 4); // 12
4.obj.assign 合并对象
  function sayName(obj){
    
    
            obj = Object.assign({
    
    
                name: "xx"
            }, obj);
            console.log(obj.name);
        }
        sayName(); // "xx"
        sayName({
    
    }); // "xx"
        sayName({
    
     name: "李白"}); // "李白"
5.环境作用域中:首先函数声明提升,然后才轮到变量声明提升。
 var a = 10;
        function fn(){
    
    
            
            console.log(a); // undefined
            return; 
            a += 30;
            var a = 20;
            console.log(a); 
        }

        fn();
        console.log(a); // 10
6.立即执行函数
// 1. 函数表达式的立即执行
var fn = function (){
    
    
	console.log("函数表达式的立即执行");
}();
// 2. 声明函数的立即执行
(function fn(){
    
    
	console.log("立即执行");
}())
(function fn(){
    
    
	console.log("立即执行");
})()
// 3. 函数表达式使用两个括号时
var fn = (function(){
    
    
	console.log("函数表达式的立即执行");
}())
var fn = (function(){
    
    
	console.log("函数表达式的立即执行");
})()
7.闭包题

闭包的本质就是:指有权访问另一个函数作用域中的变量的函数。

 function fun(n, o) {
    
    
            console.log(o);
            return {
    
    
                fun: function (m) {
    
    
                    return fun(m, n);
                }
            };
        }
第一道:
        // var a = fun(0); // undefined
        // a.fun(1); // 0     
        // a.fun(2); // 0
        // a.fun(3); // 0
第二道:链式操作

        // var b = fun(0).fun(1).fun(2).fun(3); // undefined 0 1 2
第三道:
        var c = fun(0).fun(1); // undefined 0
        c.fun(2); // 1
        c.fun(3); // 1
  • 作用:

    • 延长局部变量的生命周期
    • 让函数外部能操作内部的局部变量
  • 闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域

  • 闭包应用:

    • 回调函数
    • 模块化编码: 封装一些数据以及操作数据的函数, 向外暴露一些行为
    • 遍历添加事件监听
  • 缺点:

    • 变量占用内存的时间可能会过长

    • 可能导致内存泄露

    • 解决:及时释放 : f = null; // 让内部函数对象成为垃圾对象

  • 闭包题2

 // 闭包题1:编写一个像 sum(a)(b) = a+b 这样工作的 sum 函数。
        function sum(a, b) {
    
    
            return function (b) {
    
    
                console.log(a + b);
            }
        }
        sum(3)(-4);
  • 闭包题3
    // 闭包题2: 简化 sort 按字段排序
        // 有一组需要排序的对象
        let users = [
            {
    
     name: "John", age: 20, surname: "Johnson" },
            {
    
     name: "Pete", age: 18, surname: "Peterson" },
            {
    
     name: "Ann", age: 19, surname: "Hathaway" }
        ];

        // 通常的做法:

        // 通过 name (Ann, John, Pete)
        users.sort(function (a, b) {
    
     return a.name > b.name ? 1 : -1 });
        console.log(users);
        // 通过 age (Pete, Ann, John)
        // users.sort(function (a, b) {
    
     return a.age > b.age ? 1 : -1 });
        // console.log(users.sort());

        // 要求简化为: 根据key升序排列
        function byField(key) {
    
    
            return function (a, b) {
    
    
                return a[key] > b[key] ? 1 : -1;
            }
        }
        users.sort(byField('name'));
        console.log(users);

        users.sort(byField('age'));
        console.log(users);
// 排序后修改对象数组地址,以前打印的同一堆地址的对象数组,所以结果都一致。

猜你喜欢

转载自blog.csdn.net/weixin_47067248/article/details/107966491