闭包,原型,继承

闭包

闭包:闭包就是函数嵌套时,将局部变量进化成私有变量的环境,这个环境一般是作用域的嵌套,通俗的来说就是函数里面套函数,将原本要删除的变量,不删除,继续使用。
计算机的垃圾回收机制:不立即删,先放在临时空间内,可以二次或继续使用
特点:
闭包是将函数内部和函数外部连接起来的桥梁
可以读取函数内部的变量
让这些变量的值,始终保存在内存中,不会在调用结束后被系统回收
避免全局变量命名空间的污染
内存消耗很大,不能滥用
闭包会在父函数外部,改变父函数内部变量的值

注:一旦内部函数调用外部函数的局部变量,那么这个时候,这个局部变量就会变成内部函数的私有变量

闭包的应用:

1.循环中的事件,获取计数器的值

			 var ali = document.querySelectorAll("li");
			    for(var i=0;i<ali.length;i++){
			        ali[i].onclick = (function(a){
			            return function(){
			                console.log(a);
			            }
			        })(i)
			    }

2.在计时器的回调函数中传参

		function fn(str){
		        return function(){
		            console.log(str);
		        }
		    }
		    setTimeout(fn("html"), 1000);

利用闭包封装事件委托:

			function entrust(achild,cb){
			        return function(e){
			            for(var i=0;i<achild.length;i++){
			                if(achild[i] === e.target){
			                    cb.bind(e.target)();  //改变this指向
			                }
			            }
			        }
			    }

原型

原型:prototype
隐式原型:proto
实例:new出来的对象
构造函数:构造器,被new的那一方

		function Fn(){}
		function Fun(){}
		Fun.prototype = new Fn();
		var f = new Fn();
		var f2 = new Fun();
		console.log(Fn.prototype.constructor === Fn);       //true
	    console.log(Fn.prototype.constructor === f.__proto__.constructor);      //true
	    console.log(f.__proto__.constructor === Fn);       //true
	    console.log(Fn.prototype.constructor === f.constructor);      //true

Fn:构造函数
Fn.prototype:构造函数的原型
Fn.prototype.constructor:是构造函数的原型内的指向当前原型所在构造函数的属性
f:实例,new构造函数出来的对象,这个对象的父级是构造函数的原型
f.proto:实例的父级

**查看实例对象f是否有指针指向构造函数Fn的原型:**两种使用,如果是返回ture,如果不是返回false
**isPrototypeOf()**用于检测两个对象之间似乎否存在这种关系

				Fn.prototype.isPrototypeOf(f)    // 查看 Fn 的 prototype 对象,是否是 f 原型

instanceof运算符
注意:instanceof运算符右侧为构造函数,并且js中所有原型都来自Object构造函数

			console.log(f instanceof Fn)     // 查看 f 对象是否是构造函数 Fn 的实例
    		console.log(f instanceof Object)

原型,构造函数以及实例之间的关系图

继承

只要某个对象使用了另一个对象具有,而自身不具有的功能,就叫继承

构造函数继承:改变this指向继承
只能继承构造函数中this身上的属性和方法,不能继承原型身上的属性和方法

			 function Parent(n){
						this.num = n;
						this.show = function(){
							console.log(this.num);
						}
					}
					Parent.prototype.init = function(){
						console.log("hello");
					}
					function Child(n){
						//在Child中使用Parent中的方法和属性
						// P中的this是将来new出来的p;
						//强行将P的this指向C的this
						 Parent.call(this,n);
						 //Parent.apply(this,[n]);
						 //Parent.bind(this,n)();
					}
					var p = new Parent(12);
					p.show(); //12
					p.init(); //hello
					var c = new Child(15);
					c.show(); //15
					c.init(); //报错

原型对象继承:只能继承原型身上的属性和方法,不能继承构造函数中this的属性和方法

			 function Parent(n){
						this.num = 123;
						this.show = function(){
							console.log(this.num);
						}
					}
					Parent.prototype.init = function(){
						console.log("hello");
					}
					function Child(n){}
					//直接将原型作为一个对象复制(浅拷贝)
					//Child.prototype = Parent.prototype
					//这里更改会全部都更改,因为对象是浅拷贝的,因此要使用深拷贝,遍历一一对应
					//深拷贝
					for(var i in Parent.prototype){
						Child.prototype[i] = Parent.prototype[i];
					}
					Child.prototype.init = function(){
						console.log("html");
					}
					var p = new Parent(12);
					p.init(); //hello
					console.log(p.num); //123		
					var c = new Child(15);
					c.init(); //html
					console.log(c.num); //报错

原型链继承:既能继承原型身上的属性和方法,又能继承构造函数中的this的属性和方法,但是不方便传参

			function Parent(n){
						this.num = n;
					}
					Parent.prototype.init = function(){
						console.log("hello");
					}
					function Child(n){}
					
					Child.prototype = new Parent(15);
					
					Child.prototype.init = function(){
						console.log("html");
					}
					var p = new Parent(12);
					p.init(); //hello
					console.log(p.num); //12
					var c = new Child();
					c.init(); //html
					console.log(c.num); //15

混合继承:混合原型继承和构造函数继承,是常用的继承方式之一

				function Parent(n){
							this.num = n;
							this.show = function(){
								console.log(this.num);
							}
						}
						Parent.prototype.init = function(){
							console.log("hello");
						}
						function Child(n){
							//构造函数继承
							Parent.call(this,n);
						}
						//原型继承
						for(var i in Parent.prototype){
							Child.prototype[i] = Parent.prototype[i];
						}
						Child.prototype.init = function(){
							console.log("html");
						}
						var p = new Parent(12);
						p.init(); //hello
						console.log(p.num); //12
						
						var c = new Child(15);
						c.init(); //html
						console.log(c.num); //15

ES6继承(class继承),混合继承具有改变this指向的特性,原型链继承,是常用继承方式之一

				class Parent{
							constructor(n) {
							    this.num = n;
							}
							init(){
								console.log(this.num);
							}
						}
						class Child extends Parent{
							constructor(n){
								//类似有call,也可以接收参数
								super(n);
							}
						}
						var p = new Parent(123);
						p.init();
						
						var c = new Child(321);
						c.init();

继承的应用:一个页面有两个元素,都有拖拽,一个有边界限定,一个没有边界限定
注意:
因为利用事件监听绑定和删除事件, 所以得有事件处理函数的名字
因为需要给事件处理函数加名字, 所以要将事件处理函数单独封装
因为单独封装, 所以导致事件处理函数中的this不再指向实例
因为时间处理函数中的this不再指向实例, 所以需要使用bind方法改变this指向
因为bind每次执行会返回新函数, 所以需要提前将要改变this指向的函数使用bind处理好

	<style> 
	        .box1{width:100px;height:100px;background: red;position: absolute;left:0;top:0;}
	        .box2{width:100px;height:100px;background: blue;position: absolute;left:0;top:130px;}
	    </style>
	    <body>
			    <div class="box1"></div>
			    <div class="box2"></div>
			</body>
		<script>
				class Drag{
				        constructor(ele){
				            this.ele = ele;
				
				            this.m = this.move.bind(this);
				            this.u = this.up.bind(this);
				
				            this.addEvent();
				        }
				        addEvent(){
				            this.ele.addEventListener("mousedown",this.down(this))
				        }
				        down(that){
				            return function(e){
				                that.x = e.offsetX;
				                that.y = e.offsetY;
				                // console.log(that)
				                document.addEventListener("mousemove",that.m)
				                document.addEventListener("mouseup",that.u)
				            }
				        }
				        move(e){
				            this.ele.style.left = e.clientX - this.x + "px";
				            this.ele.style.top = e.clientY - this.y + "px";
				        }
				        up(){
				            document.removeEventListener("mousemove",this.m)
				            document.removeEventListener("mouseup",this.u)
				        }
				    }

				    class SmallDrag extends Drag{
				        constructor(ele){
				            super(ele);
				        }
				        move(e){
				            var l = e.clientX - this.x;
				            var t = e.clientY - this.y;
				            if(l<0) l=0;
				            if(t<0) t=0;
				            if(l > document.documentElement.clientWidth - this.ele.offsetWidth){
				                l = document.documentElement.clientWidth - this.ele.offsetWidth
				            }
				            this.ele.style.left = l + "px";
				            this.ele.style.top = t + "px";
				        }
				    }
				    var obox1 = document.querySelector(".box1");
				    var obox2 = document.querySelector(".box2");
				    new Drag(obox1);
				    new SmallDrag(obox2);
    	</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值