• 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());
    
  • 相关阅读:
    正则表达式 1
    14 同步 1
    14 线程属性
    14 线程状态
    14 线程
    window.location.hostname与 window.location.host 区别
    泛型 的通配符类型 extends super
    svn拷贝一个项目作为新项目
    List Collections sort
    && 和 || 逻辑运算符
  • 原文地址:https://www.cnblogs.com/zhongchao666/p/9275586.html
Copyright © 2020-2023  润新知