js中的闭包和继承

一.闭包

什么是闭包:

        闭包就是可以访问外层函数作用域中变量的函数.

        闭包的特点:

        1.会将闭包所访问的变量永远保留在计算机内存中, 可能会产生内存泄漏.

        2.闭包可以实现变量的私有化.

内存泄漏:闭包中的变量会存储在计算机内存中,且不释放,会导致计算机内存搁置,这个就叫内存泄漏。

    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <script>
        //获取所有button标签
        var buttons = document.querySelectorAll('button');
        //循环三次, 分别给三个按钮绑定点击事件
        for (var i = 0; i < buttons.length; i++) {
            buttons[i].onclick = (function (i){
                return function(){ 
    //这个内层函数就是闭包函数, 可以访问外层函数的变量( 这个变量会永远保留在计算机内存中 )
                    console.log(i);
                }
            })(i)
        }
    </script>

二.事件防抖

     事件抖动:一般情况下在网页中, 当同一个事件被频繁多次触发, 就会产生抖动. 最终出现页面频繁弹框, 频繁显示/隐藏等等. 可以借助闭包实现 事件防抖 , 最终可以实现同一事件连续多次触发结束后只处理一次(最后一次).

<input type="text" oninput="newhandleInput()">
//事件防抖:先创建一个函数,其内部打印要输出的数据
        function handleInput() {
            console.log('我要防抖');
        }
        //构建一个闭包函数,实现防抖的目的:为防止一直点击而使得服务器一直处于访问状态导致崩溃,
        //我们需要让它在一段事件内无论点击多少次,想要的数据只执行一次
        //定义一个防抖函数debounce
        function debounce(hand, time) {
            //设置外部函数的参数:要实现事件防抖,需要用到定时器,所以在外层函数中创建一个定时器,将它的值设置为空
            var timerid = null
            //返回一个内部函数
            return function () {
                //先进行条件判断,如果定时器存在,我们就销毁定时器,不存在则创建一个定时器
                //当函数执行时,定时器为空,创建一个定时器,当再次点击时进行判断,定时器存在,将他销毁,然后再判断,再销毁,
                //注意这儿不能写else,不然它只会销毁不会创建
                //循环往复,使定时器中的内容在所设置的时间内只执行一遍
                //此时定时器的值为空,我们建立一个定时器,放入我们想执行的函数,即调用handinput函数
                if (timerid) {
                    clearTimeout(timerid)
                }
                timerid = setTimeout(() => {
                    hand()
                }, time)

            }
        }
        //将debounce函数调用,并将它的值保存在一个新函数里
        var newhandleInput = debounce(handleInput, 1000)

   事件节流:

          如果原来是1s内连续执行 100次, 现在做了事件节流, 每隔0.1s执行一次, 1s内执行10次

    事件节流, 将短时间内同一事件连续多次执行, 变为每隔一段时间执行一次.

<input type="text" oninput="newhandleInput()">
//创建一个函数,内部为我们想要执行的代码
        function handleInput(){
             console.log('我要节流');
        }
        //创建一个节流函数throttle
        function throttle(hand,time){
            //写外部函数的参数创建一个空的定时器
            var timerid=null
            //闭包函数
            return function(){
                //先进行条件判断,当定时器不存在时 ,执行要输出的语句,执行完立马销毁
                //并将其设置为空,因为是在定时器所限定的时间内,所以在定时器时间到的这段时间
                //会反复进行判断,当定时结束,才会执行一次
                if(!timerid){
                    timerid=setTimeout(()=>{
                    hand()
                    //执行完立即销毁定时器
                    clearTimeout(timerid)
                    //将定时器置为空
                    timerid=null
                },time)
                }
                
            }
        }
        var newhandleInput=throttle(handleInput,100)

柯里化函数:

 // function add(a,b,c){
        //     console.log(a+b+c);
        // }

        function add(a){
            return function(b){
                return function(c){
                    console.log(a+b+c);
                }
            }
        }
        //函数的普通调用方式
        //add(10,20,30)
        //柯里化函数
        add(10)(20)(30)

三.继承

        构造函数 实现面向对象的写法

        class 实现面向对象的写法

        构造函数 或 class的写法 目的都是为了完成已有代码的封装(面向对象程序的 第一特性).

        继承(面向对象程序的 第二特性)

        实现继承的方法一: 构造函数+call

 function Father(){
            this.height = 199;
            this.color = 'yellow';
            this.money = 9999999;

            this.run = function(){
                console.log('running');
            }
        }
function Son(){
    //构造函数继承( 构造函数+call )
            Father.call(this);
    //继承了Father的所有属性和方法
        }

        var s = new Son();
        s.run();
    //s.run() 之所以能调用成功,是因为 Son这个构造函数继承了Father这个构造函数的所有属性和方法
        var s=new Son()
        console.log(s.height);

通过更改Son的原型对象, 更改为Father的实例对象, 实现了通过原型链继承Father的属性。

function Father(){
            this.height = 199;
            this.color = 'yellow';
            this.money = 9999999;

            this.run = function(){
                console.log('running');
            }
        }
        function Son(){}
        Son.prototype = new Father();
        var s1 = new Son();
        var s2 = new Son();
        var s3 = new Son();
        s.run();
   //s.run() 之所以能调用成功,是因为 Son这个构造函数继承了Father这个构造函数的所有属性和方法
        console.log(s.height,s.color,s.money);
        console.log(s1,s2,s3);

组合继承: 同时使用构造函数继承( 继承数据属性 ),原型链继承( 继承方法 )

 function Father(){
            this.height = 199;
            this.color = 'yellow';
            this.money = 9999999;
            this.run = function(){
                console.log('running');
            }
        }
        //构造函数继承
        function Son(){
            Father.call(this);
        }
        //将方法保存到原型对象身上, 使用Son构造函数创建的所有实例对象 都可以访问到该方法, 但是该方法只保存了一份(在原型对象身上)
        //原型链继承
        Son.prototype.run=function(){
            run()
        }
        // Son.prototype.run = function(){ console.log('running'); } 

        var s1 = new Son()
        var s2 = new Son()
        var s3 = new Son()
        console.log(s1,s2,s3,s1.run);

  class继承, 通过extends 关键词实现继承

        class Father {
            constructor(){
                this.height = 199;
                this.color = 'yellow';
                this.money = 9999999;
            }
            run(){
                console.log('running');
            }
        }
        //class继承, 通过extends 关键词实现继承
        class Son extends Father {}
        var s = new Son()
        console.log(s.height,s.run);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值