1. 程式人生 > >面向對象的三個特點:封裝、繼承、多態

面向對象的三個特點:封裝、繼承、多態

super student tostring 會有 我們 強行 span json 使用

封裝

1、封裝的概念

所謂封裝,就是指隱藏內部的細節,不暴露在外面。

把構造函數裏的this改成 _price;

在js裏面,實現封裝的方法非常簡單,只需要在聲明屬性的時候,添加關鍵字即可。 一般來講,對於私有屬性,有一個不成文的規定,習慣使用_來命名屬性。

封裝後的屬性(私有屬性)對於外部來講,雖然不可見,但是對於內部來講,是可見的。

總結:封裝後方法可以訪問,但是屬性信息都為undefined

2、get和set 以及屬性特性

很多時候,我們對對象的屬性進行封裝,並不是為了外部訪問不到,而是為了當外部訪問對象屬性或者設置的時候進行一定的限制。也就是說,外部能夠正常的訪問到進行限制了的屬性。

Object.defineProperty(),通過這個方法可以給對象添加屬性。

語法:Object.defineProperty(obj,prop,descriptor)

obj:目標對象

prop:需要添加到屬性

descriptor:屬性相關特性

descriptor參數是一個JSON對象,可以設置特性如下:

value:屬性的值. //或者return。和 writable 一起用 默認false

writable:屬性是否可寫

get:一旦目標屬性被訪問的時候,就調用該方法

set:一旦目標屬性被設置的時候,就調用該方法

enumerable:查看屬性是否可以枚舉,就是is hi 用for..in的時候,是否可以遍歷出來。 True false

如果要設置多個屬性,可以調用object.object.defineProperties(),這樣就可以設置多個屬性。使用該方法接收的參數也是有一定變化的

語法:object.defineProperties(obj,{JSON})

JSON對象 {prop:{descriptor},prop:{descriptor},…. }

for(let I in stu)

{

console.log(i);

}

繼承

1、繼承基本介紹

在程序語言裏面,面向對象種所指的繼承就是一個子類去繼承一個父類。子類在繼承了父類之後,父類所擁有的屬性和方法自動就都擁有了。

繼承的好處:

繼承最大的好處,就在於代碼能夠進行復用。例如有兩個類,就給他們寫個父類。

繼承缺點:

首先如果我們繼承設計得非常復雜,那麽整個程序設計也會變得龐大和復雜。

如果是像C++那樣的多繼承語言,那麽可能還會出現菱形繼承的問題。 //只有c++是多繼承。改動之後 最下層方法不知道用哪一個

單繼承:只有一個父類

多繼承:有多個類

菱形繼承問題:首先需要說明,菱形繼承問題只會在多繼承裏面才會出現。

例如:a和b是繼承base類,假設base類有一個成員方法,那麽a和b都會有這個成員方法,這個時候a和b又分別對成員方法進行了修改。接下來讓一個c來同時繼承a和b,問題來了,對於同名的方法,究竟使用哪一個,這就是所謂的菱形繼承問題。這個是屬於設計上的問題。

由於js是單繼承語言,所以一定程度上避免了菱形繼承的問題。

2、js裏面實現繼承的方法

(1)對象冒充

所謂對象冒充,就是指用父類(構造函數)去充當子類的屬性

temp=構造函數名字

但是,使用對象冒充實現的繼承有一個缺點,缺陷就是無法繼承到原型對象上面的屬性或者方法

從對象冒充又衍生出來了一種通過call或者apply來實現繼承,本質上還是對象冒充。

他倆基本上一樣,只是參數接收不同

function.call(abj,arg1,arg2,arg3…)

Function.apply(obj,[arg1,arg2,arg3,arg4…])

Obj:代表當前對象

arg:代表一個參數列表

總結:簡單來講,就是將a所擁有的東西應用到b的環境裏面,讓b也擁有和a相同的東西,但是作用域還是b的,而不是a的。

c1.show.call(c2);

(2)通過原型對象來實現繼承

這種方法的核心思路就是改變構造函數的prototype的屬性值,但是這種方式也有一個缺點,就是無法傳參

(3) 混合方式實現繼承

為了實現能夠同時傳參以及能夠繼承到原型對象上面的屬性和方法,采用上面兩種方式的結合。

Person.call(this, name, age); //call 方法

Student.prototype = new Person();

(4)es6 實現繼承的方式

埃ES6裏面添加了關鍵字extends

class 子 extends 父 {

Constructor(name,age,gender,score){

super(name,age)

This..

}

}

super//訪問父類

class Student extends Person { //extends關鍵字

constructor(name,age,gender,score){

super(name,age);//訪問父類的內容

this.gender=gender;

this.score=score;

多態

1、什麽事多態

所謂多態,就是指不同的對象的同名方法卻有不同的效果,這就是多態。

最常見的多態即使to string();

雖然每個對象都有tostring()方法,但是並不是每一個對象的表現形式都一樣的

轉數組有逗號分隔

轉數字 沒有

2、實現多態

在繼承父類當法的時候直接進行覆蓋即可,這樣就實現了多態。

(1)混合方式實現多態

給子類原型對象添加同名的方法;

調用同名方法。表現形式不一樣。

(2)es6中實現多態

類裏 方法也可以看作是一個屬性

在子類裏添加一個同名的屬性進行調用

重寫或重載。

我們重寫

擴展

1、從對象創建對象

實際上在js裏面創建對象時可以完全避免使用構造函數(或者說類,)而時使用另外一個對象作為原型來創建對象

使用

boject.create();

這個方法還可以傳入第二個參數,第二個參數是json對象,用來對對象的屬性設置相關特性。

2、混入

混入就是一種不需要繼承,就將某些對象的屬性和方法添加到另一個對象上面。通過Object.assing()來實現

語法:

Object.assign(target,a,b,c,d,…..)

Let a={ } ;

Let b={

name:”xiejie”,

age:18

}

let c={

gender:male;

score:100;

}

Object.assign(a,b,c);

Console .log(a.name);

如果混入對象中包含同名的屬性,那麽後面會覆蓋前面的。

記住:混入優於繼承

3、改寫this的指向

this默認的指向:如果是全局環境或者函數裏面調用,包括嵌套,這個this指向全局對象

Node global

瀏覽器 window

如果通過對象的方式來調用,那麽this指向當前對象。

但是,這個this的指向,我們是可以改變的

(1)通過call或者apply可以改變this的指向

(2)通過bind()方法強行綁定this指向

(3)箭頭函數的this

箭頭函數基本語法

(形參)=>{函數體}

如果只有一個參數

形參=>{函數體}

這裏與其數是箭頭函數改變了this指向,更貼切的來講,汗透函數的this指向和其他函數不一樣,箭頭函數的this指向始終是外部的作用域

面向對象的三個特點:封裝、繼承、多態