Class與建構函式的區別

2022-09-06 03:45:07 字數 4794 閱讀 2847

class在語法上更貼合物件導向的寫法。

class實現繼承更加易讀、易理解。

更易於寫j**a等後端語言的使用。

本質是語法糖,使用prototyp。

一、js建構函式

js中的prototype:每乙個建構函式都有的乙個屬性,能夠用來向物件新增屬性和方法。用來返回物件型別原型的引用。不需要顯式宣告,它是隱式存在的。

object.prototype.name = value

object.prototype.func = function()

object.prototype =object

1、原型法設計模式:現在有1個類a,我想要建立乙個類b,這個類是以a為原型的,並且能進行擴充套件。我們稱b的原型為a。

2、當乙個物件被建立時,這個建構函式 將會把它的屬性prototype賦給新物件的內部屬性__proto__。這個__proto__被這個物件用來查詢它的屬性。

3、在外部不能通過prototype改變自定義型別的屬性或方法,即當原型方法和物件方法在呼叫相同的屬性和函式時,會執行物件方法裡面的屬性和函式。

二、es6中的構造語法——class

三、語法糖

之所以叫做語法糖,不只是因為加糖前後的**實現的功能一樣,更重要的是,糖在不改變其所在位置的語法結構的前提下,實現了執行時的等價。也可以理解為,加糖前後的**編譯結果是一樣的。加糖只是為了讓**的更加簡潔,語義更加自然。

在class語法中:typeof mathhandle ----->function

mathhandle === mathhandle.prototype.constructor     // js中沒有類,class本質上還是建構函式

function定義的方法(物件方法)有乙個prototype屬性,使用new生成的物件就沒有這個prototype屬性。也就是prototype屬性是物件方法或者構造方法的專有屬性。 prototype屬性又指向了乙個prototype物件,注意prototype屬性與prototype物件是兩個不同的東西,要注意區別。在prototype物件中又有乙個constructor屬性,這個constructor屬性同樣指向乙個constructor物件,而這個constructor物件恰恰就是這個function函式本身。

function person(name)

this.name=name;

this.showme=function()

alert(this.name);

var one=new person('js');

alert(one.prototype)                              //undefined

alert(typeof person.prototype);              //object

alert(person.prototype.constructor);     //function person(name) ;

四、js繼承

1、拓展原型。可以理解為dog物件將animal中的屬性和方法全部轉殖一遍,dog能夠使用animal中的方法和屬性。

2、如果子類和父類中的方法同名,則執行時會先去本體的函式中去找,如果找到則執行,找不到則去prototype中尋找函式,理解為prototype不會轉殖同名函式。

五、es6中的繼承——class

es6中的字串佔位符:

js中:"hello" + str + "world !"

es6中:hello $ world !

js語言傳統建立物件的方法一般是通過建構函式,來定義生成的,下面是乙個使用function生成的例子。(需要了解生成物件的方式,如工廠模式、原型模式等,以及優缺點,請參考文章:j**ascript中建立物件的7種模式)

function point(x,y)

point.prototype.tostring = function()

var p= new point(1,2);

上面的例子在es6中定義如下:

class point

tostring()

}1.類point中方法之間不用,號隔開,方法不用function進行定義,

建構函式的prototype屬性,在es6的「類」上面繼續存在。事實上,類的所有方法都定義在類的prototype屬性上面。

class point

tostring()

tovalue()

}// 等同於

point.prototype = ,

tovalue(){}

};2.類的內部所有定義的方法,都是不可列舉的(但是在es5中prototype的方法是可以進行列舉的)

3.每乙個類中都有乙個constructor方法該方法返回例項物件

4.類的建構函式,不使用new是沒法呼叫的,會報錯。這是它跟普通建構函式的乙個主要區別,後者不用new也可以執行。

用類進行例項和用普通的建構函式進行例項:

1、用類進行例項的必須使用new否則就會報錯

2、與es5一樣,例項的屬性除非顯式定義在其本身(即定義在this物件上),否則都是定義在原型上(即定義在class上)。

3、與es5一樣,類的所有例項共享乙個原型物件。

4、class不存在變數提公升(hoist),這一點與es5完全不同

new foo(); // referenceerror

class foo {}

上面**中,foo類使用在前,定義在後,這樣會報錯,因為es6不會把類的宣告提公升到**頭部。這種規定的原因與下文要提到的繼承有關,必須保證子類在父類之後定義。

;class bar extends foo

}上面的**不會報錯,因為bar繼承foo的時候,foo已經有定義了。但是,如果存在class的提公升,上面**就會報錯,因為class會被提公升到**頭部,而let命令是不提公升的,所以導致bar繼承foo的時候,foo還沒有定義。

class point

}class colorpoint extends point

}上面**中,子類的constructor方法沒有呼叫super之前,就使用this關鍵字,結果報錯,而放在super方法之後就是正確的。

super.print.call(this)

類的prototype屬性和__proto__屬性

大多數瀏覽器的es5實現之中,每乙個物件都有__proto__屬性,指向對應的建構函式的prototype屬性。class作為建構函式的語法糖,同時有prototype屬性和__proto__屬性,因此同時存在兩條繼承鏈。

(1)子類的__proto__屬性,表示建構函式的繼承,總是指向父類。

(2)子類prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的prototype屬性。

class a

class b extends a

b.proto=== a // true

b.prototype.proto=== a.prototype // true

上面**中,子類b的__proto__屬性指向父類a,子類b的prototype屬性的__proto__屬性指向父類a的prototype屬性。

這樣的結果是因為,類的繼承是按照下面的模式實現的。

例項的__proto__屬性

子類例項的__proto__屬性的__proto__屬性,指向父類例項的__proto__屬性。也就是說,子類的原型的原型,是父類的原型。

原生建構函式的繼承

原生建構函式是指語言內建的建構函式,通常用來生成資料結構。ecmascript的原生建構函式大致有下面這些。

boolean()

number()

string()

array()

date()

function()

regexp()

error()

object()

以前,這些原生建構函式是無法繼承的,比如,不能自己定義乙個array的子類。

myarray.prototype = object.create(array.prototype,

});上面**定義了乙個繼承array的myarray類。但是,這個類的行為與array完全不一致。

var colors = new myarray();

colors[0] = "red";

colors.length // 0

es5是先新建子類的例項物件this,再將父類的屬性新增到子類上,由於父類的內部屬性無法獲取,導致無法繼承原生的建構函式。比如,array建構函式有乙個內部屬性[[defineownproperty]],用來定義新屬性時,更新length屬性,這個內部屬性無法在子類獲取,導致子類的length屬性行為不正常。

es6允許繼承原生建構函式定義子類,因為es6是先新建父類的例項物件this,然後再用子類的建構函式修飾this,使得父類的所有行為都可以繼承。下面是乙個繼承array的例子。

class myarray extends array

}var arr = new myarray();

arr[0] = 12;

arr.length // 1

arr.length = 0;

arr[0] // undefined

上面**定義了乙個myarray類,繼承了array建構函式,因此就可以從myarray生成陣列的例項。這意味著,es6可以自定義原生資料結構(比如array、string等)的子類,這是es5無法做到的。

上面這個例子也說明,extends關鍵字不僅可以用來繼承類,還可以用來繼承原生的建構函式。因此可以在原生資料結構的基礎上,定義自己的資料結構。

Class和普通建構函式的區別

js建構函式 function mathhandle x,y mathhandle.prototype.add function let test newmathhandle 1 2 console.log test.add console.log typeof mathhandle console...

類class的建構函式

類class的建構函式1.簡單的時鐘 include using namespace std class clock void clock settime int nh,int nm,int ns void clock showtime 2.建構函式的幾種方法 1 預設建構函式 class cloc...

拷貝建構函式與賦值建構函式的區別

class cstr protected const cstr copy const cstr str private char m pdata size t m size cstr cstr size t cstr getsize const const cstr cstr copy const ...