电饭锅的说法

day19高级函数

1.回顾

2.闭包函数

2.1基础使用

2.2使用场景

  • 扩大变量的作用域范围

     // 1.扩大变量的作用域范围的时候
        function fun1() {
            var b = "局部变量b";
            function fun2() {
                return b;
            }
            return fun2;
        }
        var res = fun1();
        var newB = res();
        console.log(newB);//"局部变量b"
        newB = null;//手动释放
  • 在for循环添加事件中,可以拿到正确的下标

/ 2.可以解决在for循环添加事件中不能得到正确下标
        // 面试题1
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr.push(function () { console.log(i) })
        }
        // for的作用就是给arr追加函数  并没有执行函数  i最后一次的值是10
        // [f,f,f,f,f,f,f,f,f]
        console.log(arr[4]);//funtion(){console.log(i)}
        arr[5]();//10
        // 怎么修改 arr[5]() 输出5 利用闭包函数解决这个问题
        var arr = [];
        for (var i = 0; i < 10; i++) {
            (function (i) {//形参
                console.log(i);//0 1 2 3.....9
                arr.push(function () {
                    console.log(i);//0 1 2 3....9
                })
            })(i)//实参 下标i
​
        }
        console.log(arr[5]);//function(){console.log(5)}
        arr[5]();//5
​
​
​
​
        // 面试题2
        var li = document.getElementsByTagName("li");
        for (var i = 0; i < 10; i++) {
            li[i].onclick = function () {
                console.log(i);//10
            }
        }
        //i最后一次的值10
        // 利用闭包函数 点击第几个li就输出对应下标
        for (var i = 0; i < 10; i++) {
            (function (i) {//形参i
                // console.log(i);//0 1 2 3 4.....9
                li[i].onclick = function () {
                    console.log(i);//0 1 2 3 4 5....9
                }
            })(i)//for循环中的i
        }
  • 模拟私有变量

 // 3.模拟私有变量  
        // 构造函数
        function Student() {
            // 私有变量必须通过函数返回出去
            var name = "小张"
            function get() {
                return name;
            }
            return get;
        }
        var res = new Student();//调用构造函数
        var res1 = res();
        console.log(res1);//"小张"

3.递归函数

  • 什么是递归:函数内部调用函数本身

    • 函数自己调用自己

    • 递归函数中的结束条件,一定要有结束条件,结束条件放在函数的最前面

  • ==报错信息:Maximum call stack size exceeded栈溢出,是因为没有写结束条件==

<script>
        // 1.6! 6*5*4*3*2*1
        /*
            6! = 6*5!
                    5! = 5*4!
                            4! = 4*3!
                                   3! = 3*2!
                                          2! = 2*1!
                                                 1! = 1
            n! = n*(n-1)!  结束条件 n=1 就结束了
​
            注意:Maximum call stack size exceeded栈溢出,是因为没有写结束条件
        */
        // 阶乘函数
        function jc(n) {//6
            if (n == 1) return 1;
            return n * jc(n - 1)
        }
        var res = jc(10);
        console.log(res);

4.快速排序

  • 快排思路

    • 1.找数组中中间的值 splice(Math.floor( arr.length / 2),1)[0]

    • 2.定义两个空数组 left right var left = [] var right = []

    • 3.拿数组中的元素依次和中间值作比较 比中间值小的放入left数组 比中间值大的放入right数组

    • 4.将left数组和中间值及right数组 组合成一个新的数组

    • ==结束条件:当数组元素只有一个值或者空数组的时候就结束了 arr.length<=1==

 function quick(arr) {//arr是比较的数组
            // 归:结束条件
            if (arr.length <= 1) return arr;
            // 1.找数组中中间的值 splice(Math.floor( arr.length / 2),1)[0]  
            var middle = arr.splice(Math.floor(arr.length / 2), 1)[0];
            console.log(middle);
            // 2.定义两个空数组 left right
            var left = [];
            var right = [];
            // 3.拿数组中的元素依次和中间值作比较  比中间值小的放入left数组  比中间值大的放入right数组
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] < middle) {
                    left.push(arr[i]);
                } else {
                    right.push(arr[i]);
                }
            }
            return quick(left).concat(middle, quick(right))
        }

5.事件频繁触发

  • 为了减少事件频繁发生的问题 我们可以使用防抖和节流解决

5.1防抖

  • 防抖的原理:利用闭包函数,在事件处理函数中添加一个定时器,在定时器延迟一定的时候再执行代码,如果定时器没有走完又去触发该事件 从头开始计时(清除原先的定时器,从新定义一个)

var oDiv = document.getElementsByTagName("div")[0];
        // 1.基础操作
        oDiv.onmousemove = function () {
            oDiv.innerHTML++;
        }
        // 2.使用防抖减少事件执行的次数
        var timer;
        oDiv.onmousemove = function () {
            //怎么去判断定时器有没有执行完 根据判断timer值
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                oDiv.innerHTML++;
            }, 500)
        }
  • 函数封装

 // 3.防抖函数封装
        function debounce(fun, wait) {
            var timer;
            function show() {
                //怎么去判断定时器有没有执行完 根据判断timer值
                if (timer) {
                    clearTimeout(timer);
                }
                timer = setTimeout(fun, wait)
            }
            return show;
        }
        oDiv.onmousemove = debounce(function () { oDiv.innerHTML++ }, 500)

5.2节流

  • 节流的原理:利用闭包函数,在事件处理函数中添加一个定时器,延迟一定的时间执行代码。在定时器执行过程中 事件状态是禁止的 等定时器完成。事件状态解开

   var oDiv = document.getElementsByTagName("div")[0];
        // 1.基础操作
        oDiv.onmousemove = show
        function show() {
            oDiv.innerHTML++;
        }
        // 2.节流减少事件触发的频率
        oDiv.onmousemove = show;
        var timer;//初始值undefined
        function show() {
            // 怎么判断定时器有没有执行完
            if (timer) return;
            timer = setTimeout(function () {
                oDiv.innerHTML++;
                timer = undefined;
            }, 500)
        }
  • 函数封装

 // 3.函数封装
        function throttle(fun, wait) {
            var timer;//初始值undefined
            function show() {
                //怎么判断定时器有没有执行完
                if (timer) return;
                timer = setTimeout(function () {
                    fun();//要做的事情有很多很多 所以放入到一个函数中
                    timer = undefined;
                }, wait)
            }
            return show;
        }
        oDiv.onmousemove = throttle(function () { oDiv.innerHTML++ }, 500)

6.面向对象

编程思想有两种

  • 面向过程:一步一步分析实现功能 注重的是过程

  • 面向对象:不管滚成是啥样的,只看结果 注重是结果

有一天你想吃鱼香肉丝了,怎么办呢?你有两个选择
1、自己买材料,肉,鱼香肉丝调料,蒜苔,胡萝卜等等然后切菜切肉,开炒,盛到盘子里。注重过程
2、去饭店,张开嘴:老板!来一份鱼香肉丝! 注重结果
看出来区别了吗?这就是1是面向过程,2是面向对象。
  • 面向对象核心:就是对象

  • 面向对象的组成

    • 方法:函数,一些具有行为的动作

    • 属性:描述性的内容 静态的

  • 特点

    • 封装

    • 继承

    • 多态

6.1面向对象的创建

1.字面量创建

==缺点:只适用于单个对象的创建==

  var obj = {
            // 属性
            "name": "张三",
            "age": 20,
            // 方法
            "work": function () {
                console.log("敲代码")
            }
        }
        // 缺点:只适用于单个对象的创建
        var obj1 = {
            // 属性
            "name": "赵四",
            "age": 30,
            // 方法
            "work": function () {
                console.log("敲代码")
            }
        }

2.使用new 关键字创建

==缺点:代码冗余==

 // 2.使用new关键字创建
        var obj = new Object();
​
        // 往空对象中添加属性和方法
        // 属性
        obj.name = "王五";
        obj.age = 20;
        // 方法
        obj.work = function () {
            console.log("敲代码")
        }
        console.log(obj);//{name: '王五', age: 20, work: ƒ}
        console.log(obj.name);
        obj.work();
​
        // 缺点:代码冗余

3.工厂模式创建

==缺点:类识别不清==

  // 3.工厂模式创建  这个函数就是用来创建人这个类(对象)
        function createObj(name, age) {
            //原材料
            var obj = new Object();
            // 加工  添加属性和方法
            obj.name = name;
            obj.age = age;
            obj.work = function () {
                console.log("敲代码");
            }
            // 出厂
            return obj
        }
​
        // 创建一个人
        var person1 = createObj("张三", 20);
        console.log(person1);
        // 创建一个人
        var person2 = createObj("李四", 30);
        console.log(person2);
        // 缺点:类识别不清
        var dog1 = createObj("大黄", 3);
        console.log(dog1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值