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("水蜜桃"));
●闭包问题
解释:
- 闭包和垃圾回收机制gc是相关联的。
- 闭包实际上是涉及到一个对象的成员属性,何时被gc处理的问题。
- 怎样才能对对象的属性形成一个闭包呢?看下面案例
//闭包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变量被闭包