Day17
●js面向对象编程—三大特征
抽象à把一类事物的共有的属性和行为提取出来,形成一个物理模板
▶封装:把抽象出的属性和对属性的操作封装在一起。
Js提供以下几种控制方法和属性的访问权限:
案例:
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("水蜜桃"));
●闭包问题
解释:
//闭包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变量被闭包