22闭包与继承

Posted zhongchao666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了22闭包与继承相关的知识,希望对你有一定的参考价值。

==闭包和面向对象都是面试的重点,==

1.闭包

一.什么是闭包函数?

嵌套在一个函数中的函数,称为闭包函数。

内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

二.闭包的作用

可以在函数外部通过闭包函数访问到函数内部的局部变量。

三.闭包原理

JS中利用垃圾回收机制清理内存中被释放的内容,当被释放的内容被另一个程序使用的时候,这内容就会被长期保留在内存。

四.闭包优缺点?

优点:可以使局部变量长驻内存,不被释放,从而让函数外部访问到该变量。
缺点:长驻内存,内存长期得不到释放,可能造成内存泄露。

            
            function me(){
                
                
                var a = 4;
                return function fn(){
                    return a;
                }
            }
            var fn1 = me();   //fn1 = function fn(){ return a;};
            alert(fn1());//4
            
            
            (function(){
                
            })()`

2.闭包的应用

使用全局变量进行累加和
使用局部变量进行累加和
循环里的匿名函数的取值问题
        <script type="text/javascript">
            var a = 3;
            function fn(){
                a ++;//全局
            }
            alert(a); //3
            fn();
            alert(a); //4
            fn();
            alert(a); //5
            
            
            function fn(){
                var a = 3;
                a ++;//局部
                alert(a);
            }
            fn(); //4
            fn(); //4
            fn(); //4

            function fn(){
                var a = 3;
                return  function(){  //闭包函数
                    return a++;  //a=4,a++ = 3
                }
            }
            alert(fn()()); //3
            alert(fn()()); //3
            alert(fn()()); //3
            
            
            function fn(){
                var a = 3;
                return  function(){  //闭包函数
                    return a++;  //a = 4
                }
            }
            var me = fn();  // var me = function(){ return a++}; //6,只执行一次me = fn(),a=3只初始化一次
            alert(me()); //3
            alert(me()); //4
            alert(me()); //5
            alert(me()); //6


        function fn(){
                var arr = [];
                for(var i = 0;i < 5;i ++){
                    arr[i] = function(){
                        return i;
                    };
                }
                return arr;
            }
            var me = fn();
            for(var i = 0;i < me.length;i ++){
                alert(me[i]());//5,5,5,5,5
            }


            function fn(){
                var arr = [];
                for(var i = 0;i < 5;i ++){
                    arr[i] = (function(){
                        return i;
                    })();
                }
                return arr;
            }
            var me = fn();
            for(var i = 0;i < me.length;i ++){
                alert(me[i]);//0,1,2,3,4
            }
        
            
            function fn(){
                var arr = [];
                for(var i = 0;i < 5;i ++){
                    arr[i] = (function(i){
                        return i;
                    })(i);
                }
                return arr;
            }
            var me = fn();
            for(var i = 0;i < me.length;i ++){
                alert(me[i]);//0,1,2,3,4
            }
            

            function fn(){
                var arr = [];
                for(var i = 0;i < 5;i ++){
                    arr[i] = (function(i){ 
                        //0
                        /*
                         * function(){
                            return i;
                        };
                        i = 1;
                        function(){
                            return i;
                        };
                        i = 2;
                        function(){
                            return i;
                        };
                        i = 3;
                        function(){
                            return i;
                        };
                        i = 4;
                        function(){
                            return i;
                        };
                         */
                        return function(){
                            return i;
                        };
                    })(i);
                }
                return arr;
            }
            var me = fn();
            for(var i = 0;i < me.length;i ++){
                alert(me[i]());//0,1,2,3,4
            }

面向对象

// ES6:

class 类名{
    constructor([参数]){
        this.属性名 = 属性值;
        ……
    }
    方法名([参数]){
        处理语句
    }
    ……
}

class 子类名 extends 父类名{
    constructor([参数]){
        super([参数]);
        this.属性名 = 属性值;
        ……
    }
    方法名([参数]){
        处理语句
    }
}


//ES5:

function 类名([参数]){
    this.属性名 = 属性值;
    ……
}
类名.prototype.方法名 = function([参数]){
    处理语句
}

function 子类名([参数]){
    父类名.apply(this,arguments);
    this.属性名 = 属性值;
}
for(var i in 父类.prototype){
    子类.prototype[i] = 父类.prototype[i];
}
子类名.prototype.方法名 = function([参数]){
    处理语句;
}

3.es5面向对象

创建构造函数
缺点:浪费内存空间

==实例继承==

call(当前对象,参数1,参数2,参数3,……)
apply(当前对象,[参数1,参数2,参数3,……])
apply(当前对象,arguments)

        //创建构造函数
            function Father(name,age){
                //实例属性或实例方法
                //属性
                this.name = name;
                this.age = age;
                //方法
                this.showName = function(){
                    return this.name;
                }
                this.showAge = function(){
                    return this.age;
                }
                this.song = function(){
                    return ‘唱歌‘;
                }
            }
            var fa1 = new Father(‘张三‘,18);
            var fa2 = new Father(‘张三‘,20);
            console.log(typeof fa1.showName);//function
            console.log(typeof fa2.showName);//function
            console.log(fa1 === fa2);//false
            console.log(fa1.song === fa2.song);//false //函数存在堆里,栈里存的是地址.
            console.log(fa1.name === fa2.name);//true
            //缺点:浪费内存空间
            
            //继承
            function Son(name,age){
                //继承实例属性或实例方法
                //经典继承
                //call(当前对象,参数1,参数2,参数3,……)
                //apply(当前对象,[参数1,参数2,参数3,……])
                //apply(当前对象,arguments)
//              Father.call(this,name,age); //继承父类的实例属性和实例方法
//              Father.apply(this,[name,age]);
                Father.apply(this,arguments);
            }
            var son = new Son(‘李四‘,18);
            alert(son.showName());//李四

==原型继承==

Prototype : 原型
原型缺点:无法传参,所有的对象都具有相同的属性值。

==原型继承== Son.prototype = Father.prototype;

==原型链继承==Son.prototype = new Father();

==拷贝继承==
var son = new Son();
//拷贝继承
for(var i in Father.prototype){
??Son.prototype[i] = Father.prototype[i];
}

//创建构造函数
            function Father(){
        
            }
        
            //原型属性
            Father.prototype.name = ‘张三‘;
            Father.prototype.age = 18;
            //原型方法
            Father.prototype.showName = function(){
                return this.name;
            }
            Father.prototype.showAge = function(){
                return this.age;
            }
            Father.prototype.song = function(){
                return ‘唱歌‘;
            }
            var fa1 = new Father();
            var fa2 = new Father();
//          console.log(typeof fa1.showName);
//          console.log(typeof fa2.showName);
//          console.log(fa1 === fa2);
            console.log(fa1.song === fa2.song);
//          console.log(fa1.name === fa2.name);
            //原型缺点:无法传参,所有的对象都具有相同的属性值。
            
            
            function Son(){}
            
            //原型继承
            
//          Son.prototype = Father.prototype;
//          Son.prototype = new Father();//原型链继承
            var son = new Son(); 
            //拷贝继承
            for(var i in Father.prototype){
                Son.prototype[i] = Father.prototype[i];
            }
            alert(son.song());

==混合继承==

既有实例继承,也有原型继承

            //创建构造函数
            function Father(name,age){
                //实例属性
                this.name = name;
                this.age = age;
            }
            //Prototype : 原型
            
            //原型方法
            Father.prototype.showName = function(){
                return this.name;
            }
            Father.prototype.showAge = function(){
                return this.age;
            }
            Father.prototype.song = function(){
                return ‘唱歌‘;
            }
            var fa1 = new Father();
            var fa2 = new Father();
//          console.log(typeof fa1.showName);
//          console.log(typeof fa2.showName);
//          console.log(fa1 === fa2);
            console.log(fa1.song === fa2.song);
//          console.log(fa1.name === fa2.name);
            
            
            //混合继承
            function Son(name,age){
                //实例继承
                Father.apply(this,arguments);
            }
            
            //拷贝继承
            for(var i in Father.prototype){
                Son.prototype[i] = Father.prototype[i];
            }
            
            var son = new Son(‘张三‘,18); 
            var son1 = new Son(‘李四‘,20);
            alert(son.showName == son1.showName);

es5关于实例和原型的拓展

==in== : 判断一个属性是否属于某个类,属于返回true,不属于返回false

            if(‘long‘ in Father){
                alert(‘ok‘);
            }else{
                alert(‘no‘);
            }

==delete== : 删除对象的实例属性

            delete fa.name;     
            delete Father.prototype.name;       
            alert(fa.showName());
//创建构造函数
            function Father(name,age){
                //实例属性
                this.name = name;
                this.age = age;
            }
            //Prototype : 原型
            Father.prototype.name = ‘张三‘;
            //原型方法
            Father.prototype.showName = function(){
                return this.name;
            }
            Father.prototype.showAge = function(){
                return this.age;
            }
            Father.prototype.song = function(){
                return ‘唱歌‘;
            }
            var fa1 = new Father();
            var fa2 = new Father();
//          console.log(typeof fa1.showName);
//          console.log(typeof fa2.showName);
//          console.log(fa1 === fa2);
            console.log(fa1.song === fa2.song);
//          console.log(fa1.name === fa2.name);
            
            
            //混合继承
            function Son(name,age){
                //实例继承
                Father.apply(this,arguments);
            }
            
            
            
//          Son.prototype = Father.prototype;
//          Son.prototype = new Father();//原型链继承
            
            //拷贝继承
            for(var i in Father.prototype){
                Son.prototype[i] = Father.prototype[i];
            }
            
            var fa = new Father(‘李四‘,20);
            fa.name = ‘王五‘;
//          alert(fa.showName());
            //in : 判断一个属性是否属于某个类,属于返回true,不属于返回false
//          if(‘long‘ in Father){
//              alert(‘ok‘);
//          }else{
//              alert(‘no‘);
//          }
            //delete : 删除对象的实例属性
            delete fa.name;
            delete Father.prototype.name;
            alert(fa.showName());//undefined

增加和修改现有类的方法

给Array添加求和方法:

            Array.prototype.mySum = function(){
                var sum = this.reduce(function(up,down){
                    return up + down;
                })
                return sum;
            }

修改数组的.push()方法:

            Array.prototype.push = function(){
                alert(‘呵呵‘);
            }
            var arr = [1,2,3,4,5];
            
            alert(arr.mySum());
            alert(arr.push());










以上是关于22闭包与继承的主要内容,如果未能解决你的问题,请参考以下文章

深入理解javascript原型和闭包——继承

javaScript闭包实现类与继承(非ES6)

原型链 ,闭包与继承

从零开始学习前端JAVASCRIPT — 14闭包与继承

js继承与闭包(笔记)

Python 简明教程 --- 22,Python 闭包与装饰器