首页 > 代码库 > JavaScript基础--面向对象三大特性(八):继承封装多态

JavaScript基础--面向对象三大特性(八):继承封装多态

 

一、构造函数
基本用法:
function 类名(参数列表){
属性=参数值
}

 1 function Person(name,age){
 2    this.name = name;
 3    this.age = age;
 4 }
 5 
 6 //创建Person对象的时候,可以直接给名字和年龄
 7 var p1 = new Person(‘abc‘,80);
 8 window.alert(p1.name);
 9 var p2 = new Person(‘hello‘,9);
10 window.alert(p2.name);
11 
12 //在给一个对象初始化普通属性值的时候,也可以指定函数属性
13 
14        function jiSuan(num1,num2,oper){
15         if(oper=="+"){
16            return num1 + num2;
17         }else if(oper=="-"){
18            return num1 - num2;
19         }else if(oper=="*"){
20            return num1 * num2;
21         }else{
22            return num1 / num2;
23         }
24     }
25 
26     function Person(name,age,fun){
27         this.name = name;
28         this.age =age;
29         this.myfun = fun;
30     }
31     
32     //创建对象时,不仅要可以初始化变量,还可以初始化一个函数
33     var p1 = new Person("aa",9,jiSuan);
34         window.alert(p1.myfun(90,89,"+"));

 

二、创建对象的有一种形式【加强篇】

    2.1 JSON创建对象

//如果一个对象比较简单,我们可以直接创建。(可以指定普通属性和函数)
   var dog ={name:‘小狗‘,age:8};
   window.alert(dog.constructor);
   window.alert(dog.name + dog.age);

//扩展:
    var dog = {name:‘小狗‘,
           age:8,
           fun1:function(){window.alert(‘hello,world‘);},
           fun2:function(){window.alert(‘okok‘);}
           };
    window.alert(dog.constructor);
    window.alert(dog.name + dog.age);
    dog.fun1();
    dog.fun2();


//有时,我们看到这样一种调用方法,函数名.call(对象实例)
//这样调用,该函数的this就是对象实例
var dog ={name:‘hello‘};
function test(){
   window.alert(this.name);
}
test();
window.test();
//这两个方法都打印出undefine
test.call(dog);  //<==>dog.test();

    2.2 使用for...in 遍历

 1 var dog= {name:‘小明‘,sayHello:function(a,b){window.alert("结果="+(a+b));}};
 2 //循环列出dog对象的所有属性和方法 对象名[‘属性名‘]
 3 for(var key in dog){
 4    window.alert(dog[key]); 
 5 }
 6 
 7 //document.write("****当前浏览器window对象所有属性和方法****<br/>");
 8 for(var key in window){
 9    document.writeln(key+":"+window[key]+"<br/>");
10 }

 

三、JS面向对象的三大特性:继承、封装和多态

   3.1 封装

  js提供有以下几种控制方法和属性的访问权限:
    (1) 公开级别:对外公开
    (2) 私有级别:类本身可用访问,不对外公开。

 1 function Person(name,agei,sal){
 2       this.name = name;  //公开的属性 
 3       var age=agei;   //私有属性
 4       var salary=sal; //私有属性
 5       //在类中如何定义公开方法(特权方法),私有方法(内部方法)
 6       //如果我们希望操作私有的属性,则可用公开方法实现
 7       this.show=function(){
 8        window.alert(age+" "+salary);
 9       }
10        
11       //私有方法
12       function show2(){
13             window.alert(age+" "+salary);
14       }
15       show2();
16    }
17   
18    var p1 = new Person(‘sp‘,20,50000);
19    window.alert(p1.name+" "+p1.age);
20    p1.show(); //这个可以ok
21    //p1.show2(); //不能在类的外部使用私有的方法

    

 1 //注意:通过prototype给所有的对象添加方法,但是这种方式,不能去访问类的私有变量和
 2 
 3 //方法
 4    //举例:
 5     function Person(){
 6        this.name = "abc";
 7        var age=90;
 8     this.abc=function(){
 9             window.alert("abc()");
10         }
11 
12         function abc2(){
13             window.alert("abc2");
14         }
15     }
16 
17     Person.prototype.fun1 =function(){
18           window.alert(this.name); //ok
19         //window.alert(age);  //no ok  私有变量
20       //abc2(); //no ok   私有方法
21       //window.alert(age);  //no ok   私有变量
22  
23     }
24     
25     var p1 = new Person();
26     p1.fun1();

 

     3.2 继承

        A、为什么需要继承

 1 function MidStu(name,age){
 2      this.name=name;
 3      this.age = age;
 4      this.show =function(){
 5         window.alert(this.name +" "+this.age);
 6      }
 7      //计算学费
 8      this.payFee=function(money){
 9          window.alert("应缴" + money * 0.8);
10       }
11   } 
12 
13   function Pupil(name,age){
14      this.name=name;
15      this.age = age;
16      this.show =function(){
17         window.alert(this.name +" "+this.age);
18      }
19      //计算学费
20      this.payFee=function(money){
21          window.alert("应缴" + money * 0.5);
22       }
23   } 
24    //上面的代码存在冗余问题

 

 

//解决方法可以使用继承(对象冒充来实现继承效果的)
    
   //怎么解决代码冗余问题-->继承
   //抽象出一个学生类(把小学生和中学生的共性取出)

   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;
        this.stu(name,age); //js中实际上是通过对象冒充,来实现继承,这句话不能少。

    //因为js是动态语言,如果不执行,则不能实现继承效果
        //MidStu可以覆盖Stu父类的show
        this.show=function(){
           window.alert("MidStu show();");
        }
   }                         

   function Pupil(name,age){
         this.stu = Stu;
         this.stu(name,age);
   }
  
   var midStu = new MidStu("顺平",20);
   window.alert(midStu.name);
   midStu.show();

//特别说明:通过对象冒充,js可以实现多重继承的效果,用的比较少

   

3.3  js的重载和重写

        3.3.1 重载:js中不支持重载(即,不可用通过参数的个数来决定调用哪个函数,但是因为js本身支
持可变参数,所有,它可以看成天然支持重载)

   

1 function abc(){
2    if(argument.length=..){
3     }else if(){
4     }
5 }

 

        3.3.2 重写:子类可以重新写函数来覆盖父类的某个方法

//父类
 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;
        this.stu(name,age); //js中实际上是通过对象冒充,来实现继承,这句话不能少。

//因为js是动态语言,如果不执行,则不能实现继承效果
        //MidStu可以覆盖Stu父类的show
        /*this.show=function(){
           window.alert("MidStu show();");//这里就会去调用子类的show方法
        }*/
   }                         
   var midStu = new MidStu("zhangsan",3);
   midStu.show();

 

   3.4 多态:一个引用类型在不同情况下的多种状态,在java中多态是指通过父类的引用,来调用在不同子类中实现的方法。js实际上是无态的,是一种动态语言,一个变量的类型是在运行的过程中由js引擎来决定的,所有说,js天生就是支持多态。

 1 function Person(){
 2   this.test1=function(){
 3       window.alert("Person test1");
 4   }
 5 }
 6 function Cat(){
 7   this.test1=function(){
 8        window.alert("Cat test1()");
 9   }
10 }
11 var  v = new Person();
12 v.test1();
13 v = new Cat();
14 v.test1();

       3.4.1 面向对象三大特征案例

 1 function Master(){
 2         //给动物喂食
 3        this.feed =function(animal,food){
 4             document.write("主人给"+animal.name + "喂"+food.name);
 5        }
 6     }
 7 
 8     //写食物
 9     function Food(name){
10         this.name =name;
11     }
12 
13     function Fish(name){
14         this.food = Food;
15         this.food(name);
16     }
17 
18     function Bone(name){
19          this.food = Food;
20          this.food(name);
21     }
22 
23     function Peach(name){
24          this.food = Food;
25          this.food(name);
26     }
27 
28     //动物
29     function Animal(name){
30           this.name=name;
31     }
32     
33     function Cat(name){
34           this.animal=Animal;
35           this.animal(name);
36     }
37 
38     function Dog(name){
39           this.animal = Animal;
40           this.animal(name);
41     }
42 
43     function Monkey(name){
44            this.animal = Animal;
45            this.animal(name);
46     }
47 
48     var cat = new Cat("小猫咪");
49     var dog = new Dog("小狗");
50     var fish = new Fish("小鱼");
51     var bone = new Bone("骨头");
52 
53     var master = new Master();
54     master.feed(cat,fish);
55     master.feed(dog,bone);
56     master.feed(new Monkey("小猴"),new Peach("水蜜桃"));

 

四、闭包

     4.1 解释:

    (1)闭包和gc是相关联的
    (2)闭包实际是涉及到一个对象的属性,何时被gc处理的问题
    (3)怎样才能对对象的属性形成一个闭包

 1 //案例:  
 2  function A(){
 3         var i=0;
 4         function b(){
 5             window.alert(i++);
 6         }
 7         return b;
 8    }
 9    var c =A();  //执行完A函数后,i的值已变成1,然后把b的构造函数赋值给c,但是i在A函数中,虽然A已执行完,但是i没有被立即回收,而是在C函数中继续执行,这样i就被闭包了。
10    c();
11   /*闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖于a中的变量i*/

分析:
//闭包<---->gc
A();//此时内存中会有i的空间被gc处理
var c = A(); //这种用法,gc不会把i当做垃圾
//c();
window.alert("aa");
//..
//..
c(); //输出0;
c(); //输出1;从而证明i变量被闭包