js_day17--js面向对象三大特征+闭包


Day17


js面向对象编程三大特征

   抽象à把一类事物的共有的属性和行为提取出来,形成一个物理模板

   封装:把抽象出的属性和对属性的操作封装在一起。

      Js提供以下几种控制方法和属性的访问权限:

  1. 公开级别:对外公开
  2. 私有级别:类本身可以访问,不对外公开

案例:

			function Person(name,agei,sal){
				this.name = name	;//公开的属性
				var age = agei;//私有属性
				var salary = sal;//私有属性
				//在类中,如何定义公开方法(特权方法),私有方法(内部方法)
				//如果我们希望操作私有的属性,则可用公开方法去实现
				this.show=function(){
					window.alert(age+" "+salary);	
				}
				//私有方法,可以访问对象的属性
				function show2(){
					window.alert(age+" " +salary);	
				}
			}
			
			var p1 = new Person("Gavin",20,50000);
			//window.alert(p1.name+" "+p1.age);//age undefined
			p1.show();//可以运行
			p1.show2();//不能在类的外部去使用私有的方法

我们前面学习过:通过prototype给所有对象添加方法,但是这种方式不能去访问类的私有变量和私有方法。

                    举例:

			function Person(){
				this.name ="abc";
				var age=90;
				
				this.abc = function(){
					window.alert("abc()");
				}
				
				function abc2(){
					window.alert("abc2()");
				}
			}
			
			Person.prototype.fun1=function(){
				window.alert(this.name);	//Ok
				window.alert(this.age);// No Ok
				this.abc(); // Ok 
				abc2();//No OK
			}
			var p1 = new Person();
			p1.fun1();

  继承

      为什么需要继承:

          继承可以解决代码复用。

      问题提出:

			//中学生
			function MidStu(name,age ){
				this.name = name;
				this.age = age;
				this.show = function(){
					window.alert(this.name+" "+this.age);
				}
				
				//计算学费
				this.payFee = function(money){
					window.alert("应缴"+money*0.8);
				}
			}
			
			//小学生
			function Pupil(name,age){
				this.name = name;
				this.age = age;	
				
				this.show = function(){
					window.alert(this.name+" "+this.age);
				}
				
				//计算学费
				this.payFee = function(money){
					window.alert("应缴"+money*0.5);
				}
			}

上面的代码存在冗余问题,

   解决方法可以使用继承(对象冒充的方法)

   如下:

			//怎么解决代码冗余问题-->继承
			//抽象出一个学生类,即把中学生和小学生的共性取出
			function Stu(name ,age){
				this.name = name;
				this.age = age;
				this.show = function(){
					window.alert(this.name+" "+this.age);
				}
			}
			
			function MidStu (name,age){
				this.stu = Stu;//把构造函数赋给了stu这个属性
				window.alert(Stu);//这里会把Stu类所有的信息打印
				this.stu(name,age);//js中实际上是通过对象冒充,来实现继承
				//这句话不能少。(因为js是动态语言,如果不执行,则不能实现继承效果)
			}
			function Pupil(name,age){
				this.stu = Stu;
				this.stu(name,age);	
			}
			
			var mid = new MidStu("Gavin",20);
			mid.show();//可以调用

特别说明:

   ☞js通过对象冒充的方式可以实现多重继承的效果

☞Object类是js所有类的基类

  方法重载和方法覆盖

   Js不支持方法重载(即不可以通过参数的个数来决定调用哪个函数),但从另一个方面来看,js也是天然支持方法重载的,因为它支持可变参数,方法的参数可以随意传进去,所以可以根据arguments数组的长度判断参数个数来实现不同的代码。

function abc(){
			if(arguments.length == ?){

}else if (…){

}
}

在子类中可以覆盖父类的方法。

				//MidStu可以覆盖Stu父类的方法show
				this.show = function(){
					window.alert("MidStu show()");	
				}

这时候如果调用mid.show();调用的就是子类的show方法。

  多态:天然支持多态

      所谓多态就是一个引用(类型)在不同情况下的多种状态,在java中多态是指通过指向父类的引用,来调用在不同子类中实现的方法。

             Js实际上是无态的,是一种动态语言,一个变量的类型是在运行的过程中由js引擎来决定的。所以说他天然支持多态。(无招胜有招)。

             案例:

			//多态的案例
			//主人类
			function Master(){
				//写一个给动物喂食物的方法。
				this.feed = function(animal,food){
						alert(animal.constructor);
						document.write("主人给"+animal.name+"喂"+food.name);
				}	
			}
			//食物类
			function Food(name){
				this.name = name;
				//...	
			}
			
			function Fish(name){
				this.food = Food;
				this.food(name);	
			}
			function Bone(name){
				this.food  = Food;
				this.food(name);	
			}
			
			function Taozi(name){
				this.food  = Food;
				this.food(name);	
			}
			
			//动物
			function Animal(name){
				this.name = name;
				//...	
			}
			
			function Cat(name){
				this.animal = Animal;
				this.animal(name);	
			}
			
			function Dog(name){
					this.animal = Animal;
					this.animal(name);	
			}
			
			function Monkey(name){
					this.animal = Animal;
					this.animal(name);	
			}
			
			var cat = new Cat("小猫咪");
			var dog = new Dog("小狗");
			var fish = new Fish("小鱼");
			var bone = new Bone("骨头");
			
			var master = new Master();
			master.feed(cat,fish);
			master.feed(dog,bone);
			master.feed(new Monkey("小猴"),new Taozi("水蜜桃"));

●闭包问题      

解释:

  1. 闭包和垃圾回收机制gc是相关联的。
  2. 闭包实际上是涉及到一个对象的成员属性,何时被gc处理的问题。
  3. 怎样才能对对象的属性形成一个闭包呢?看下面案例
			//闭包closure-->回收的时机问题
			function A(){
				var i = 0;
				function b(){
					alert(i++);	
				}	
				return b;
			}
			//闭包<--->gc
			A();//此时内存中肯定有i的空间,gc会把i回收,因为没有变量接收
			var c = A();//相当于把b给了c,c中用到了变量i,这时候gc不会对i回收
			c();//这时候打印了i的值0
			c();//这时候打印了i的值1,从而证明了i变量被闭包






你可能感兴趣的:(继承,闭包,多态)