国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

js中的面向對象是什么

發(fā)布時(shí)間:2021-09-04 11:55 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 開(kāi)發(fā)技術(shù)

本篇內容主要講解“js中的面向對象是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強。下面就讓小編來(lái)帶大家學(xué)習“js中的面向對象是什么”吧!

什么是對象

我們先來(lái)看高程三中是如何對對象進(jìn)行定義的

"無(wú)序屬性的集合,其屬性可以包括基本值、對象或者函數",對象是一組沒(méi)有特定順序的的值。對象的沒(méi)個(gè)屬性或方法都有一個(gè)俄名字,每個(gè)名字都映射到一個(gè)值。

簡(jiǎn)單來(lái)理解對象就是由屬性和方法來(lái)組成的

面向對象的特點(diǎn)

封裝

對于一些功能相同或者相似的代碼,我們可以放到一個(gè)函數中去,多次用到此功能時(shí),我們只需要調用即可,無(wú)需多次重寫(xiě)。

在這里我們可以理解為創(chuàng )造對象的幾種模式:?jiǎn)卫J?,工廠(chǎng)模式,構造函數模式,原型模式等。

繼承

子類(lèi)可以繼承父類(lèi)的屬性和方法

多態(tài)(重載和重寫(xiě))

  • 重載:嚴格意義上說(shuō)js中沒(méi)有重載的功能,不過(guò)我們可以通過(guò)判斷函數的參數的不同來(lái)實(shí)現不同的功能來(lái)模擬重載。

  • 重寫(xiě):子類(lèi)可以改寫(xiě)父類(lèi)的屬性和方法

javascript中的封裝

單例模式

小王在一個(gè)小公司,就自己一個(gè)前端,所以他寫(xiě)js都是這樣的

var a = 1;
function getNum(){
 return 1;
}

后來(lái)公司又招了個(gè)前端小明,于是變成他們2個(gè)一起寫(xiě)同一個(gè)js了。一天小王發(fā)現自己寫(xiě)的getNum方法出問(wèn)題了,原來(lái)是小華寫(xiě)的js中也有個(gè)getNum的函數,代碼合并后把他的覆蓋掉了,于是便找小華理論去,經(jīng)過(guò)一番妥協(xié)后,兩人都把自己的代碼改了改

var xiaoming = {
 num:1,
 getNum:function(){
 return 1;
 }
}
var xiaohua = {
 num:2,
 getNum: function(){
 return 2;
 }
}

這就是我們所謂的單例模式(命名空間)

我們把描述同一個(gè)事物的方法或者屬性放到同一個(gè)對象里,不同事物之間的方法或者屬性名相同相互也不會(huì )發(fā)生沖突。

單例模式的優(yōu)劣

1.使用單例模式,我們可以實(shí)現簡(jiǎn)單的模塊化開(kāi)發(fā)

var utils = {
getCss:function(){
 //code
},
getByClass:function(){
 //code
},
setCss:function(){
 //code
}
}

我們可以把自己寫(xiě)好的工具方法放到一個(gè)單獨的js文件中,然后直接引入即可。

2.避免了全局變量名的沖突

需要注意的是,我們在引入各個(gè)模塊的時(shí)候,需要注意引入的順序,引入順序是按照各模塊之間的相互依賴(lài)進(jìn)行前后排列的;

3.缺點(diǎn):

  • 單例模式只是一定程度上避免了變量名的沖突,但并不能徹底解決此問(wèn)題,而且在不同的對象下,我們可能會(huì )有很多功能相同的代碼,最終造成大量的冗余代碼。

  • 單例模式讓每個(gè)對象有了自己獨立的命名空間,但是并不能批量生產(chǎn)的問(wèn)題,每一個(gè)新的對象都要重新寫(xiě)一份一模一樣的代碼。

var person1 = {
 name:'小明',
 age:24,
 showName:function(){
  console.log('我的名字是:'+this.name)
 }
};
var person1 = {
 name:'小華',
 age:25,
 showName:function(){
  console.log('我的名字是:'+this.name)
 }
};

工廠(chǎng)模式

1.工廠(chǎng)模式其實(shí)就是把需要一個(gè)個(gè)的編寫(xiě)的對象,放在一個(gè)函數中統一的進(jìn)行創(chuàng )建,說(shuō)白了就是普通函數的封裝。

2.工廠(chǎng)模式總共3步驟:

1)引進(jìn)原材料 --- 創(chuàng )建一個(gè)空對象

2)加工原材料 --- 加工對象:給對象添加屬性和方法;

3)輸出產(chǎn)品 --- 返回對象:return 對象;

function CreatePerson(name,age){
 var obj={};//1.創(chuàng  )建一個(gè)空對象
 //2.加工對象
 obj.name=name;
 obj.age=age;
 obj.showName=function(){
  console.log('我的名字是:'+this.name)
 };
 return obj;//3.輸出對象;
}
var person1 = CreatePerson('小明',23)
var person2 = CreatePerson('小華',23)
person1.showName(); //我的名字是:小明
person2.showName(); //我的名字是:小華

工廠(chǎng)模式的優(yōu)缺點(diǎn)

既然叫工廠(chǎng)模式,它就和我們周?chē)墓S(chǎng)一樣,我們只需要把原材料放進(jìn)去,就能得到我們需要的產(chǎn)品了。

工廠(chǎng)模式也解決了單例模式的批量生產(chǎn)的問(wèn)題,避免了單例模式中的大量冗余代碼,進(jìn)行系統的封裝,提高代碼的重復利用率

不過(guò)工廠(chǎng)模式跟我們js內置類(lèi)的調用方法不同

構造函數模式

  • 可以創(chuàng )建一個(gè)自定義的類(lèi),并且可以new出實(shí)例

  • 構造函數做的就是類(lèi)和實(shí)例打交道。

 //構造函數:首字母大寫(xiě)(約定俗成);
 function CreatePerson(name,age){ //創(chuàng  )建一個(gè)自定義的類(lèi)
 //構造函數中的this,都是new出來(lái)的實(shí)例
 //構造函數中存放的都是私有的屬性和方法;
 this.name=name;
 this.age=age;
 this.showName=function(){
  console.log('我的名字是:'+this.name)
 }
 }
 //實(shí)例1
 var person1 = new CreatePerson('小明',25)
 //實(shí)例2
 var person2 = new CreatePerson('小華',24)

這里說(shuō)一下工廠(chǎng)模式和構造函數模式的區別:

1. 在調用的時(shí)候不同:

工廠(chǎng)模式:調用的時(shí)候,只是普通函數的調用createPerson();

構造函數模式:new CreatePerson();

2. 在函數體內不同:

工廠(chǎng)模式有三步:1)創(chuàng )建對象 2)加工對象 3)返回對象;

構造函數模式只有1步: 只有加工對象; 因為系統默認會(huì )為其創(chuàng )建對象和返回對象;

3. 構造函數默認給我們返回了一個(gè)對象,如果我們非要自己手動(dòng)返回的話(huà):

    (1)手動(dòng)返回的是字符串類(lèi)型:對以前實(shí)例上的屬性和方法沒(méi)有影響;

    (2)手動(dòng)返回的是引用數據類(lèi)型:以前實(shí)例身上的屬性和方法就被覆蓋了;實(shí)例無(wú)法調用屬性和方法;

構造函數的方法都是私有方法,每個(gè)實(shí)例調用的都是自己私有的方法,同樣也會(huì )有許多重復的代碼。

我們可以使用原型模式來(lái)解決每個(gè)實(shí)例中都有相同方法的函數的問(wèn)題

原型模式

 function CreatePerson(name,age){ 
 this.name=name;
 this.age=age;
 }
 // 我們把公有的方法放到函數的原型鏈上
 CreatePerson.prototype.showName = function(){
  console.log('我的名字是:'+this.name)
 } 
 var person1 = new CreatePerson('小明',25) 
 var person2 = new CreatePerson('小華',24)
 person1.showName() //小明

###### 原型模式的關(guān)鍵:

1)每個(gè)函數數據類(lèi)型(普通函數,類(lèi))上,都有一個(gè)屬性,叫prototype。

2)prototype這個(gè)對象上,天生自帶一個(gè)屬性,叫constructor:指向當前這個(gè)類(lèi);

3)每個(gè)對象數據類(lèi)型(普通對象,prototype,實(shí)例)上都有一個(gè)屬性,

   叫做__proto__:指向當前實(shí)例所屬類(lèi)的原型;

這3句話(huà)理解了,下邊的東西就可以不用看了 //手動(dòng)滑稽

通過(guò)例子我們來(lái)看這幾句話(huà)是什么意思

 function CreatePerson(name,age){
 this.name=name;
 this.age=age
}
CreatePerson.prototype.showName=function(){
  console.log('我的名字是:'+this.name)
}
var person1 = new CreatePerson('小明',25);
console.dir(person1)

在chrome瀏覽器控制臺中顯示

從圖中可以看出,person1這個(gè)對象上有name和age兩個(gè)屬性,person1的__proto__指向了它的構造函數(CreatePerson)的prototype上,而且還有一個(gè)showName的方法。

并且它們中有一條鏈關(guān)聯(lián)著(zhù): person1.__proto__ === CreatePerson.prototype

接著(zhù)來(lái)看

function Foo(){
 this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo; //沒(méi)有參數的話(huà)括號可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

以這個(gè)為例,當我們查找f1.a時(shí),因為f1中有這個(gè)屬性,所以我們得出 f1.a=1;當我們查找f1.b時(shí),f1中沒(méi)有這個(gè)屬性,我們便順著(zhù)f1.__proto__這條鏈去它的構造器的prototype上找,所以我們得出了 f1.b = 3;

接著(zhù)來(lái)說(shuō),Foo.prototype是個(gè)對象,那么它的__proto__指向哪里呢

還記的剛剛說(shuō)的那句

每個(gè)對象數據類(lèi)型(普通對象,prototype,實(shí)例)上都有一個(gè)屬性,叫做__proto__:指向當前實(shí)例所屬類(lèi)的原型

此外,我們應該知道

每一個(gè)對象都是function Object這個(gè)構造函數的實(shí)例

所以我們可以接著(zhù)還原這個(gè)原型圖

等等,圖上貌似多了個(gè)個(gè)Object.prototype.__proto__ 指向了null,這是什么鬼?

我們這么來(lái)理解,Object.prototype是個(gè)對象,那么它的__proto__指向了它的構造函數的prototype上,最后發(fā)現了還是指向它自身,這樣轉了個(gè)圈貌似是無(wú)意義的,于是便指向了null還沒(méi)完,我們發(fā)現對象都是函數(構造器)創(chuàng )造出來(lái)的,那么函數是誰(shuí)創(chuàng )造的呢?石頭里蹦出來(lái)的么?

在js中,function都是由function Function這個(gè)構造器創(chuàng )造的,每一個(gè)函數都是Function的實(shí)例

現在基本上我們就能得出了完整的原型圖了

是不是有點(diǎn)亂?根據我們剛剛講的是能把這個(gè)圖理順的,這里需要注意下,Function.__proto__是指向它的prototype的

多說(shuō)一點(diǎn),判斷數據類(lèi)型的方法時(shí),我們知道有個(gè)instanceof的方法

比如

A instanceof B

instanceof判斷的規則就是:

沿著(zhù)A的__proto__這條線(xiàn)查找的同時(shí)沿著(zhù)B的prototype這條線(xiàn)來(lái)找,如果兩條線(xiàn)能找到同一個(gè)引用(對象),那么就返回true。如果找到終點(diǎn)還未重合,則返回false。

再來(lái)看我們之前的那個(gè)例子

function Foo(){
 this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo; //沒(méi)有參數的話(huà)括號可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

當我們查找f1.a時(shí),因為f1中有這個(gè)屬性,所以我們得出 f1.a=1;

當我們查找f1.b時(shí),f1中沒(méi)有這個(gè)屬性,我們便順著(zhù)f1.__proto__這條鏈去它的構造器的prototype上找,所以我們得出了 f1.b = 3;

當我們查找一個(gè)對象的屬性時(shí),先在這個(gè)對象的私有空間內查找,如果沒(méi)找到,就順著(zhù)對象的__proto__這條鏈去它的構造器的ptototype上查找,如果還沒(méi)找到,接著(zhù)沿__proto__向上查找,直到找到Object.prototype還沒(méi)有的話(huà),這個(gè)值就為undefined,這就是所謂的原型鏈

列舉下網(wǎng)頁(yè)中的一些相關(guān)的原型鏈

有興趣的同學(xué)可自行通過(guò)瀏覽器控制臺看看我們常用的方法都是在哪個(gè)類(lèi)上定義的,比如getElementsByTagName,addEventListener等等

繼承

在這里就主要說(shuō)一下組合繼承(call + 原型鏈)

function Father(){
 this.xxx= 80;
 this.yyy= 100;
 this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
 this.aaa = 120;
 this.singing = function(){}
 Father.call(this);
}
Son.prototype = new Father;
Son.prototype.constructor = Son;
var son = new Son
console.dir(son)

這么寫(xiě)有個(gè)不好的地方就是:子類(lèi)私有的屬性中有父類(lèi)私有的屬性,子類(lèi)公有的屬性中也有父類(lèi)私有的屬性;

根據我們前邊的知識,我們可以這么來(lái)改寫(xiě)

function Father(){
 this.xxx= 80;
 this.yyy= 100;
 this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
 this.aaa = 120;
 this.singing = function(){}
 Father.call(this); //利用call繼承了父類(lèi)的私有屬性
}
Son.prototype.__proto__ = Father.prototype
var son = new Son
console.dir(son)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

js
久久久久亚洲AV无码专区首| 国产成人18黄网站免费观看| 久久婷婷五月综合色欧美蜜芽| 精品国产AⅤ无码一区二区| 成全视频在线观看在线播放高清| 玩两个丰满老熟女|