首页 > 代码库 > 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变量被闭包