Bootstrap

想品客老师的第六天:函数

函数基础的部分写在这里

函数声明

在js里万物皆对象,函数也可以用对象的方式定义

    let func = new Function("title", "console.log(title)");
        func('我是参数title');

也可以对函数赋值:

  let cms = function (title) {
            console.log(title);
        };//表达式这里有写分号
        cms("后盾人");

es6新增了简写模式

举个栗子:围绕对用户模块的设置,在对象里面写方法

       let user = {
            name: null,
            setUsername(name) {
                this.name = name;
            },
            getUsername() {
                return this.name;
            }
        };
        user.setUsername("荷叶饭");
        console.log(user.getUsername());//荷叶饭

正常情况对方法的声明应该是【setUsername:function(){this.name-name;}】

es6的简写是【 setUsername(name) {this.name = name;}】可以不用写冒号和function

全局函数定义特点

我们普通的在全局写一个函数,会把函数托到全局上,自动给他一个window对象:

   function screenX(){
            console.log('我是screenX函数,已经有一个和我一样的函数名了')
        }
        console.log(window.screenX)

像这样:

但是实际上window里本来就有一个screenX属性,他们名字一样,新的会覆盖旧的,旧的旧不起作用了

    console.log(window.screenX)//返回浏览器左边界到操作系统桌面左边界的水平距离。

这就是全局变量的缺点

匿名函数

匿名函数就是没名字的函数,函数的调用可以写在函数的声明前

   show()//荷叶饭
        function show() {
            console.log('荷叶饭')
        }

这叫函数提升 函数提升看这里

函数的本质也是个对象

 console.log(hd instanceof Object)//true

立即执行函数与块作用域解决冲突

在引入其他人的库的时候,会出现函数名重复的问题,解决办法有两个:模块化类的思想和立即执行函数(之前也讲过)

在引入外来库的时候,我们可以通过自己给库私有化:

  <script src="./0124Js1.js"></script>
    <script src="./0124Js2.js"></script>
    <script>
        js1.hd()//把两个名字一样的函数封装在两个不要太的对象里
        js2.hd()//这样就不会冲突了
  </script>

看看立即执行函数:

js1:

(function(window) {
  function hd() {
    console.log("4.1.js-hd");
  }
  function show() {
    console.log("4.1.js-show");
  }
  window.js1 = { hd, show };
})(window);//不加window在全局调用不了,所以把它封装在window里

js2:

(function (window) {//把window传入
    function hd() {
        console.log("4.2.js-hd");
    }
    function show() {
        console.log("4.2.js-show");
    }
    window.js2 = { hd, show };
})(window);//把window传入

  作用域也可以看这里

形参和实参

形参就是函数里占位置的,形参的数量一般要和实参的数量对应

默认参数

给形参设置默认值

   function avg(total, year = 1) {
              console.log(year);//year=1
              return Math.round(total / year);
            }
            console.log(avg(2000))//year=1当作默认值传入函数,结果等于2000

 再举一个例子:

    function sortArray(array, type = "asc") {
            return array.sort((a, b) => (type == "asc" ? a - b : b - a));
        }
        console.log(sortArray([3, 1, 4, 2], "asc"));

这时候就按升序排序,如果传递的实参不是asc,按降序:

        function sortArray(array, type = "asc") {
            return array.sort((a, b) => (type == "asc" ? a - b : b - a));
        }
        console.log(sortArray([3, 1, 4, 2], "dasc"));

默认参数一般放在后面,放在后面在传递实参的时候可以不传,但是放在前面必须传递undefined:

 function sortArray(array, type = "asc") {
            return array.sort((a, b) => (type == "asc" ? a - b : b - a));
        }
        console.log(sortArray([3, 1, 4, 2]))//不报错
     function sortArray(type = "asc",array ) {
            return array.sort((a, b) => (type == "asc" ? a - b : b - a));
        }
        console.log(sortArray(undefined,[3, 1, 4, 2]))//传undefined不报错

函数参数

函数的参数也可以是函数,在filter里传函数:

       function fun(a) {
            return a <= 3
        }
        let arr = [1, 2, 3, 4, , 5, 6, 7].filter(fun)
        console.log(arr)//[1,2,3]

还讲到了参数不定数的时候,使用arguments参数,也就是可变参数,动态参数

arguments的一个属性:length,获取到的参数的长度

 function sum() {
            console.log(arguments.length)//6
        }
        console.log(sum(1, 2, 35, 4, 6, 22))

arguments本质上是一个对象:

function sum() {
            console.log(typeof arguments)//object
        }
        console.log(sum(1, 2, 35, 4, 6, 22))

剩余参数

也可以用剩余参数:

剩余参数:函数参数使用,得到真数组,吸收

展开运算符:数组中使用,数组展开,释放

   function sum(...args) {
            return args.reduce((a, b) => a + b);
        }
        console.log(sum(1, 23, 3, 43, 45, 53))//168

箭头函数

此事在这篇博客里亦有记载

递归、构造、事件处理的时候都用不了箭头函数

递归

边界条件和递归方程组成,这是阶乘的递归组成:

     function factorial(num) {
            if (num == 1) return 1
            return num * factorial(num - 1)
        }
        console.log(factorial(5))//5的阶乘=120

更简单的写法可以这么写:

function factorial(num) {
            return num == 1 ? 1 : num * factorial(--num);
        }
        console.log(factorial(5))//5的阶乘=120

写一个递归求和

  function sum(...args) {
            console.log(args)
            if (args.length == 0) {
                return 0
            }
            return args.pop() + sum(...args)
        }
        console.log(sum(1,2,3,4,5))

递归实现倒三角

        function star(sum) {
            return sum? document.write("*".repeat(sum) + "<br/>") || star(--sum): "";
        }
        star(5);

递归渲染

function change(lessons, num = 100, i = 0) {
        if (i == lessons.length) {
            return lessons;
        }
        lessons[i].click += num;
        return change(lessons, num, ++i);//i必须是++i,不能是i++,因为i需要先自增再传递,如果
        //++的话,传递给函数change的i永远是0
    }
    console.table(change(lessons, 90));

渲染:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>后盾人</title>
  </head>
  <body></body>
  <script>
    let lessons = [
      {
        title: "媒体查询响应式布局",
        click: 89
      },
      {
        title: "FLEX 弹性盒模型",
        click: 45
      },
      {
        title: "GRID 栅格系统",
        click: 19
      },
      {
        title: "盒子模型详解",
        click: 29
      }
    ];
    lessons = lessons.map(function(item) {
      item.click += 100;
      return item;
    });
    console.table(lessons);
  </script>
</html>

先写到这吧。。今天舟车劳顿好累好困

;