Javascript基于對(duì)象三大特性(封裝性、繼承性、多態(tài)性)
Javascript基于對(duì)象的三大特征和C++,Java面向?qū)ο蟮娜筇卣饕粯?,都是封裝(encapsulation)、繼承(inheritance )和多態(tài)(polymorphism )。只不過(guò)實(shí)現(xiàn)的方式不同,其基本概念是差不多的。其實(shí)除三大特征之外,還有一個(gè)常見(jiàn)的特征叫做抽象(abstract),這也就是我們?cè)谝恍嫌袝r(shí)候會(huì)看到面向?qū)ο笏拇筇卣鞯脑蛄恕?/p>
一、封裝性
封裝就是把抽象出來(lái)的數(shù)據(jù)和對(duì)數(shù)據(jù)的操作封裝在一起,數(shù)據(jù)被保護(hù)在內(nèi)部,程序的其它部分只有通過(guò)被授權(quán)的操作(成員方法),才能對(duì)數(shù)據(jù)進(jìn)行操作。
案例:
<html> <head> <script type="text/javascript"> function Person(name, agei, sal){ // 公開(kāi) 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封裝只有兩種狀態(tài),一種是公開(kāi)的,一種是私有的。
通過(guò)構(gòu)造函數(shù)添加成員方法和通過(guò)原型法添加成員方法的區(qū)別
1、通過(guò)原型法分配的函數(shù)是所有對(duì)象共享的.
2、通過(guò)原型法分配的屬性是獨(dú)立.(如果你不修改屬性,他們是共享)
3、建議,如果我們希望所有的對(duì)象使用同一一個(gè)函數(shù),最好使用原型法添加函數(shù),這樣比較節(jié)省內(nèi)存.
案例:
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();
特別強(qiáng)調(diào):我們前面學(xué)習(xí)的通過(guò)prototype給所有的對(duì)象添加方法,但是這種方式不能去訪問(wèn)類的私有變量和方法。
二、繼承性
繼承可以解決代碼復(fù)用,讓編程更加靠近人類思維。當(dāng)多個(gè)類存在相同的屬性(變量)和方法時(shí),可以從這些類中抽象出父類,在父類中定義這些相同的屬性和方法,所有的子類不需要重新定義這些屬性和方法,只需要通過(guò)繼承父類中的屬性和方法。
JS中實(shí)現(xiàn)繼承的方式
1、對(duì)象冒充
案例:
<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; // 通過(guò)對(duì)象冒充來(lái)實(shí)現(xiàn)繼承的 // 對(duì)象冒充的意思就是獲取那個(gè)類的所有成員,因?yàn)閖s是誰(shuí)調(diào)用那個(gè)成員就是誰(shuí)的,這樣MidStu就有了Stu的成員了 this.stu(name, age); this.payFee = function(){ window.alert("繳費(fèi)" + money * 0.8); } } function Pupil(name, age) { this.stu = Stu; // 通過(guò)對(duì)象冒充來(lái)實(shí)現(xiàn)繼承的 this.stu(name, age); this.payFee = function(){ window.alert("繳費(fèi)" + 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、通過(guò)call或者apply實(shí)現(xiàn)
案例:
<html> <head> <script type="text/javascript"> //1. 把子類中共有的屬性和方法抽取出,定義一個(gè)父類Stu function Stu(name,age){ // window.alert("確實(shí)被調(diào)用."); this.name=name; this.age=age; this.show=function(){ window.alert(this.name+"年齡是="+this.age); } } //2.通過(guò)對(duì)象冒充來(lái)繼承父類的屬性的方法 function MidStu(name,age){ //這里這樣理解: 通過(guò)call修改了Stu構(gòu)造函數(shù)的this指向, //讓它指向了調(diào)用者本身. Stu.call(this,name,age); //如果用apply實(shí)現(xiàn),則可以 //Stu.apply(this,[name,age]); //說(shuō)明傳入的參數(shù)是 數(shù)組方式 //可以寫MidStu自己的方法. this.pay=function(fee){ window.alert("你的學(xué)費(fèi)是"+fee*0.8); } } function Pupil(name,age){ Stu.call(this,name,age);//當(dāng)我們創(chuàng)建Pupil對(duì)象實(shí)例,Stu的構(gòu)造函數(shù)會(huì)被執(zhí)行,當(dāng)執(zhí)行后,我們Pupil對(duì)象就獲取從 Stu封裝的屬性和方法 //可以寫Pupil自己的方法. this.pay=function(fee){ window.alert("你的學(xué)費(fèi)是"+fee*0.5); } } //測(cè)試 var midstu=new MidStu("zs",15); var pupil=new Pupil("ls",12); midstu.show(); midstu.pay(100); pupil.show(); pupil.pay(100); </script> </html>
小結(jié):
1、JS對(duì)象可以通過(guò)對(duì)象冒充,實(shí)現(xiàn)多重繼承
2、Object類是所有Js類的基類
三、多態(tài)性
JS的函數(shù)重載
這個(gè)是多態(tài)的基礎(chǔ),在之前的Javascript入門已經(jīng)說(shuō)過(guò)了,JS函數(shù)不支持多態(tài),但是事實(shí)上JS函數(shù)是無(wú)態(tài)的,支持任意長(zhǎng)度,類型的參數(shù)列表。如果同時(shí)定義了多個(gè)同名函數(shù),則以最后一個(gè)函數(shù)為準(zhǔn)。
案例:
<html> <head> <script type="text/javascript"> //*****************說(shuō)明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中不支持重載. //但是這不會(huì)報(bào)錯(cuò),js會(huì)默認(rèn)是最后同名一個(gè)函數(shù),可以看做是后面的把前面的覆蓋了。 p1.test1("a","b"); p1.test1("a");*/ //js怎么實(shí)現(xiàn)重載.通過(guò)判斷參數(shù)的個(gè)數(shù)來(lái)實(shí)現(xiàn)重載 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()被調(diào)用"+a); } this.show2=function(a,b){ window.alert("show2()被調(diào)用"+"--"+a+"--"+b); } function show3(a,b,c){ window.alert("show3()被調(diào)用"); } } var p1=new Person(); //js中不支持重載. p1.test1("a","b"); p1.test1("a"); </script> </html>
1、多態(tài)基本概念
多態(tài)是指一個(gè)引用(類型)在不同情況下的多種狀態(tài)。也可以理解成:多態(tài)是指通過(guò)指向父類的引用,來(lái)調(diào)用在不同子類中實(shí)現(xiàn)的方法。
案例:
<script type="text/javascript"> // Master類 function Master(name){ this.nam=name; //方法[給動(dòng)物喂食物] } //原型法添加成員函數(shù) 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); } //動(dòng)物類 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("桃"); //創(chuàng)建一個(gè)主人 var master=new Master("zs"); master.feed(dog,bone); master.feed(cat,fish); master.feed(monkey,peach); </script>
多態(tài)利于代碼的維護(hù)和擴(kuò)展,當(dāng)我們需要使用同一類樹上的對(duì)象時(shí),只需要傳入不同的參數(shù)就行了,而不需要再new 一個(gè)對(duì)象。
下面是其他網(wǎng)友的補(bǔ)充
要分享Js一些基礎(chǔ)理論知識(shí),但是在項(xiàng)目中卻十分實(shí)用?;叵胫耙淮瘟钊诵乃榈拿嬖?,等了將近50分鐘,可是面試卻不到10分鐘,我的心里受到成噸的打擊與傷害,以前一直不注重扎實(shí)基礎(chǔ),當(dāng)面試官坐下的那一刻我就感到氣氛不對(duì),首先介紹自己軟件工程畢業(yè)…….然后面試官說(shuō)介紹一下軟件的幾大特性……..我…..我說(shuō)不出話,然后跳過(guò),讓我介紹一下閉包、原型、js三大特性,以及在項(xiàng)目中的運(yùn)用……我的天……當(dāng)時(shí)腦海里浮現(xiàn)的全是我在哪….我是誰(shuí)…..我在干嘛…..我還要繼續(xù)坐在這里嗎……可能現(xiàn)在說(shuō)起來(lái)比較讓人想笑,可是當(dāng)時(shí)的心情確實(shí)是很難受的,所以,從那以后,開(kāi)始注重自己的基礎(chǔ)理論知識(shí),好吧,讓我們回到正題,let's go!
封裝
首先,我們先了解一下什么是Js封裝,就是當(dāng)你需要隱藏一些屬性和方法是,就可以將這些屬性和方法封裝起來(lái),然后通過(guò)一個(gè)外部可以調(diào)用的特定接口(也可以說(shuō)是一個(gè)公共的方法)進(jìn)行調(diào)用。例如:
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====女
請(qǐng)看代碼后的注釋,this指向的都是共有的屬性和方法,而直接通過(guò)var聲明的則屬于私有變量(即外部不可訪問(wèn)變量),然后通過(guò)一個(gè)共有的show方法將私有的age和sex輸出。當(dāng)然show方法也要通過(guò)this聲明才可以喲,否則的話show方法也是不可訪問(wèn)的。
繼承
繼承其實(shí)就是當(dāng)多個(gè)方法存在相同的屬性和方法是,就把這些相同的屬性和方法提取到一個(gè)公共的方法中,通過(guò)原型prototype繼承該方法,當(dāng)然你也可以通過(guò)call或apply來(lái)繼承該方法中的屬性和方法。
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);
最終的結(jié)果如下:
當(dāng)然,個(gè)人感覺(jué)那個(gè)prototype沒(méi)有說(shuō)的很好,如果看到這篇博客的你有更好的建議或意見(jiàn)的話,歡迎給我留言。還有call和apply,其實(shí)它們的作用是一樣的,都是改變this指向,然后它們的區(qū)別也可以從代碼中看出,傳參方式不同。
多態(tài)
最后要說(shuō)多態(tài)了,寫這篇文章之前,自己對(duì)多態(tài)還是處于懵逼的狀態(tài),查閱了不少其他同行的博客,以及W3C 上的解釋,把這些總結(jié)了一下,多態(tài)就是在執(zhí)行同一操作且作用于不同對(duì)象時(shí),返回不同的結(jié)果 。其實(shí)也就是把做什么和由誰(shuí)去做分開(kāi),這樣使得代碼更容易維護(hù),且條例清晰。直接上例子吧:
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); //最終輸出的結(jié)果如下: /* Cat bite! Dog bite */
終于寫完了,如果以上有錯(cuò)誤的話,歡迎指出~
以上就是Javascript基于對(duì)象三大特性,希望對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
Javascript將string類型轉(zhuǎn)換int類型
今天網(wǎng)站有個(gè)小功能要判斷用戶購(gòu)買商品數(shù)量是否大于庫(kù)存數(shù)據(jù),如果大于庫(kù)存數(shù)量,就給予提示。2010-12-12js中g(shù)etter和setter用法實(shí)例分析
這篇文章主要介紹了js中g(shù)etter和setter用法,結(jié)合實(shí)例形式分析了javascript中g(shù)etter和setter的功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-08-08JavaScript+Html5實(shí)現(xiàn)按鈕復(fù)制文字到剪切板功能(手機(jī)網(wǎng)頁(yè)兼容)
在學(xué)習(xí)javascript的過(guò)程中,遇到一個(gè)問(wèn)題就是基于JavaScript+Html5實(shí)現(xiàn)按鈕復(fù)制文字到剪切板功能,下面小編給大家分享下我的實(shí)現(xiàn)思路,感興趣的朋友可以參考下2017-03-03js getBoundingClientRect使用方法詳解
這篇文章主要介紹了js getBoundingClientRect使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07微信小程序?qū)崿F(xiàn)導(dǎo)航欄選項(xiàng)卡效果
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)導(dǎo)航欄選項(xiàng)卡效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02