Javascript基于对象的三大特征和C++,Java面向对象的三大特征一样,都是封装(encapsulation)、继承(inheritance )和多态(polymorphism )。只不过实现的方式不同,其基本概念是差不多的。其实除三大特征之外,还有一个常见的特征叫做抽象(abstract),这也就是我们在一些书上有时候会看到面向对象四大特征的原因了。
一、封装性
封装就是把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。
案例:
<html> <head> <script type="text/javascript"> function Person(name, agei, sal){ // 公开 this.name = name; // 私有 var age = agei; var salary = sal; } var p1 = new Person('zs', 20, 10000); window.alert(p1.name + p1.age); </script> </head> <body> </body> </html>
PS:JS封装只有两种状态,一种是公开的,一种是私有的。
通过构造函数添加成员方法和通过原型法添加成员方法的区别
1、通过原型法分配的函数是所有对象共享的.
2、通过原型法分配的属性是独立.(如果你不修改属性,他们是共享)
3、建议,如果我们希望所有的对象使用同一一个函数,最好使用原型法添加函数,这样比较节省内存.
案例:
function Person(){ this.name="zs"; var age=20; this.abc=function(){ window.alert("abc"); } function abc2(){ window.alert("abc"); } } Person.prototype.fun1=function(){ window.alert(this.name);//ok //window.alert(age);//no ok //abc2();//no ok this.abc();//ok } var p1=new Person(); p1.fun1();
特别强调:我们前面学习的通过prototype给所有的对象添加方法,但是这种方式不能去访问类的私有变量和方法。
二、继承性
继承可以解决代码复用,让编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过继承父类中的属性和方法。
JS中实现继承的方式
1、对象冒充
案例:
<html> <head> <script type="text/javascript"> 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; // 通过对象冒充来实现继承的 // 对象冒充的意思就是获取那个类的所有成员,因为js是谁调用那个成员就是谁的,这样MidStu就有了Stu的成员了 this.stu(name, age); this.payFee = function(){ window.alert("缴费" + money * 0.8); } } function Pupil(name, age) { this.stu = Stu; // 通过对象冒充来实现继承的 this.stu(name, age); this.payFee = function(){ window.alert("缴费" + money * 0.5); } } var midStu = new MidStu("zs", 13); midStu.show(); var pupil = new Pupil("ls", 10); pupil.show(); </script> </head> <body> </body> </html>
2、通过call或者apply实现
案例:
<html> <head> <script type="text/javascript"> //1. 把子类中共有的属性和方法抽取出,定义一个父类Stu function Stu(name,age){ // window.alert("确实被调用."); this.name=name; this.age=age; this.show=function(){ window.alert(this.name+"年龄是="+this.age); } } //2.通过对象冒充来继承父类的属性的方法 function MidStu(name,age){ //这里这样理解: 通过call修改了Stu构造函数的this指向, //让它指向了调用者本身. Stu.call(this,name,age); //如果用apply实现,则可以 //Stu.apply(this,[name,age]); //说明传入的参数是 数组方式 //可以写MidStu自己的方法. this.pay=function(fee){ window.alert("你的学费是"+fee*0.8); } } function Pupil(name,age){ Stu.call(this,name,age);//当我们创建Pupil对象实例,Stu的构造函数会被执行,当执行后,我们Pupil对象就获取从 Stu封装的属性和方法 //可以写Pupil自己的方法. this.pay=function(fee){ window.alert("你的学费是"+fee*0.5); } } //测试 var midstu=new MidStu("zs",15); var pupil=new Pupil("ls",12); midstu.show(); midstu.pay(100); pupil.show(); pupil.pay(100); </script> </html>
小结:
1、JS对象可以通过对象冒充,实现多重继承
2、Object类是所有Js类的基类
三、多态性
JS的函数重载
这个是多态的基础,在之前的Javascript入门已经说过了,JS函数不支持多态,但是事实上JS函数是无态的,支持任意长度,类型的参数列表。如果同时定义了多个同名函数,则以最后一个函数为准。
案例:
<html> <head> <script type="text/javascript"> //*****************说明js不支持重载***** /*function Person(){ this.test1=function (a,b){ window.alert('function (a,b)'); } this.test1=function (a){ window.alert('function (a)'); } } var p1=new Person(); //js中不支持重载. //但是这不会报错,js会默认是最后同名一个函数,可以看做是后面的把前面的覆盖了。 p1.test1("a","b"); p1.test1("a");*/ //js怎么实现重载.通过判断参数的个数来实现重载 function Person(){ this.test1=function (){ if(arguments.length==1){ this.show1(arguments[0]); }else if(arguments.length==2){ this.show2(arguments[0],arguments[1]); }else if(arguments.length==3){ this.show3(arguments[0],arguments[1],arguments[2]); } } this.show1=function(a){ window.alert("show1()被调用"+a); } this.show2=function(a,b){ window.alert("show2()被调用"+"--"+a+"--"+b); } function show3(a,b,c){ window.alert("show3()被调用"); } } var p1=new Person(); //js中不支持重载. p1.test1("a","b"); p1.test1("a"); </script> </html>
1、多态基本概念
多态是指一个引用(类型)在不同情况下的多种状态。也可以理解成:多态是指通过指向父类的引用,来调用在不同子类中实现的方法。
案例:
<script type="text/javascript"> // Master类 function Master(name){ this.nam=name; //方法[给动物喂食物] } //原型法添加成员函数 Master.prototype.feed=function (animal,food){ window.alert("给"+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 Peach(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 fish=new Fish("鱼"); var dog=new Dog("狗"); var bone=new Bone("骨头"); var monkey=new Monkey("猴"); var peach=new Peach("桃"); //创建一个主人 var master=new Master("zs"); master.feed(dog,bone); master.feed(cat,fish); master.feed(monkey,peach); </script>
多态利于代码的维护和扩展,当我们需要使用同一类树上的对象时,只需要传入不同的参数就行了,而不需要再new 一个对象。
下面是其他网友的补充
要分享Js一些基础理论知识,但是在项目中却十分实用。回想之前一次令人心碎的面试,等了将近50分钟,可是面试却不到10分钟,我的心里受到成吨的打击与伤害,以前一直不注重扎实基础,当面试官坐下的那一刻我就感到气氛不对,首先介绍自己软件工程毕业…….然后面试官说介绍一下软件的几大特性……..我…..我说不出话,然后跳过,让我介绍一下闭包、原型、js三大特性,以及在项目中的运用……我的天……当时脑海里浮现的全是我在哪….我是谁…..我在干嘛…..我还要继续坐在这里吗……可能现在说起来比较让人想笑,可是当时的心情确实是很难受的,所以,从那以后,开始注重自己的基础理论知识,好吧,让我们回到正题,let's go!
封装
首先,我们先了解一下什么是Js封装,就是当你需要隐藏一些属性和方法是,就可以将这些属性和方法封装起来,然后通过一个外部可以调用的特定接口(也可以说是一个公共的方法)进行调用。例如:
function Person(name , age , sex){ this.name = name ; //共有变量 var age = age ; //私有变量 var sex = sex ; //私有变量 this.show = function (){ console.log(age+"===="+sex); } } var person = new Person('Sunshine',18,'女'); console.log(person.age); // undefined console.log(person.name); // Sunshine console.log(person.show()); // 18====女
请看代码后的注释,this指向的都是共有的属性和方法,而直接通过var声明的则属于私有变量(即外部不可访问变量),然后通过一个共有的show方法将私有的age和sex输出。当然show方法也要通过this声明才可以哟,否则的话show方法也是不可访问的。
继承
继承其实就是当多个方法存在相同的属性和方法是,就把这些相同的属性和方法提取到一个公共的方法中,通过原型prototype继承该方法,当然你也可以通过call或apply来继承该方法中的属性和方法。
function Person(name , age , sex){ this.name = name ; this.age = age ; this.sex = sex ; this.show = function (){ console.log( this.age + "========"+ this.sex ); } } function Student(name , age , sex , score){ this.score = score ; Person.apply(this,[name , age , sex]); } function Worker(name , age , sex , job){ this.job = job ; Person.call(this,name , age , sex); } Dancer.prototype = new Person('Sunshine',18,'女'); function Dancer(salary ){ this.salary = salary ; } var student = new Student('Sunshine',18,'女',100); var worker = new Worker('Sunshine',18,'女','IT'); var dancer = new Dancer(20000); console.log(student); console.log(worker); console.log(dancer);
最终的结果如下:
当然,个人感觉那个prototype没有说的很好,如果看到这篇博客的你有更好的建议或意见的话,欢迎给我留言。还有call和apply,其实它们的作用是一样的,都是改变this指向,然后它们的区别也可以从代码中看出,传参方式不同。
多态
最后要说多态了,写这篇文章之前,自己对多态还是处于懵逼的状态,查阅了不少其他同行的博客,以及W3C 上的解释,把这些总结了一下,多态就是在执行同一操作且作用于不同对象时,返回不同的结果 。其实也就是把做什么和由谁去做分开,这样使得代码更容易维护,且条例清晰。直接上例子吧:
function dwn(s){ document.write(s+"<br/>"); } function Animal(){ this.bite=function(){ dwn("animal bite!"); } } function Cat(){ this.bite=function(){ dwn("Cat bite!"); } } Cat.prototype=new Animal(); ///inherit Animal function Dog(){ this.bite=function(){ dwn("Dog bite"); } } Dog.prototype=new Animal(); ///inherit Animal function AnimalBite(animal){ if(animal instanceof Animal) //这里是判断animal的原型是否指向Animal animal.bite(); } var cat = new Cat(); var dog = new Dog(); AnimalBite(cat); AnimalBite(dog); //最终输出的结果如下: /* Cat bite! Dog bite */
终于写完了,如果以上有错误的话,欢迎指出~
以上就是Javascript基于对象三大特性,希望对大家的学习有所帮助。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]