//函數名和實例化構造名相同且大寫(非強制,但這麼寫有助於區分構造函數和普通函數) function Person(name,age) { this.name = name; this.age=age; } Person.prototype.say = function(){ return "個人名字叫" + this.name+"今年"+this.age+"歲了"; } var obj=new Person("laotie",88);//經過構造函數建立對象,必須使用new 運算符 console.log(obj.say());//個人名字叫laotie今年88歲了
構造函數生成實例的執行過程:javascript
1.當使用了構造函數,而且new 構造函數(),後臺會隱式執行new Object()建立對象; 2.將構造函數的做用域給新對象,(即new Object()建立出的對象),而函數體內的this就表明new Object()出來的對象。 3.執行構造函數的代碼。 4.返回新對象(後臺直接返回);
ES6引入了Class(類)這個概念,經過class關鍵字能夠定義類。該關鍵字的出現使得其在對象寫法上更加清晰,更像是一種面向對象的語言。若是將以前的代碼改成ES6的寫法就會是這個樣子:java
class Person{//定義了一個名字爲Person的類 constructor(name,age){//constructor是一個構造方法,用來接收參數 this.name = name;//this表明的是實例對象 this.age=age; } say(){//這是一個類的方法,注意千萬不要加上function return "個人名字叫" + this.name+"今年"+this.age+"歲了"; } } var obj=new Person("laotie",88); console.log(obj.say());//個人名字叫laotie今年88歲了
注意項函數
1.在類中聲明方法的時候,千萬不要給該方法加上function關鍵字 2.方法之間不要用逗號分隔,不然會報錯
由下面代碼能夠看出類實質上就是一個函數。類自身指向的就是構造函數。因此能夠認爲ES6中的類其實就是構造函數的另一種寫法!this
console.log(typeof Person);//function console.log(Person===Person.prototype.constructor);//true
如下代碼說明構造函數的prototype屬性,在ES6的類中依然存在着。console.log(Person.prototype);//輸出的結果是一個對象
實際上類的全部方法都定義在類的prototype屬性上。代碼證實下:spa
Person.prototype.say=function(){//定義與類中相同名字的方法。成功實現了覆蓋! return "我是來證實的,你叫" + this.name+"今年"+this.age+"歲了"; } var obj=new Person("laotie",88); console.log(obj.say());//我是來證實的,你叫laotie今年88歲了
固然也能夠經過prototype屬性對類添加方法。以下:prototype
Person.prototype.addFn=function(){ return "我是經過prototype新增長的方法,名字叫addFn"; } var obj=new Person("laotie",88); console.log(obj.addFn());//我是經過prototype新增長的方法,名字叫addFn
還能夠經過Object.assign方法來爲對象動態增長方法code
Object.assign(Person.prototype,{ getName:function(){ return this.name; }, getAge:function(){ return this.age; } }) var obj=new Person("laotie",88); console.log(obj.getName());//laotie console.log(obj.getAge());//88
constructor方法是類的構造函數的默認方法,經過new命令生成對象實例時,自動調用該方法。對象
class Box{ constructor(){ console.log("啦啦啦,今每天氣好晴朗");//當實例化對象時該行代碼會執行。 } } var obj=new Box();
constructor方法若是沒有顯式定義,會隱式生成一個constructor方法。因此即便你沒有添加構造函數,構造函數也是存在的。constructor方法默認返回實例對象this,可是也能夠指定constructor方法返回一個全新的對象,讓返回的實例對象不是該類的實例。blog
class Desk{ constructor(){ this.xixi="我是一隻小小小小鳥!哦"; } } class Box{ constructor(){ return new Desk();// 這裏沒有用this哦,直接返回一個全新的對象 } } var obj=new Box(); console.log(obj.xixi);//我是一隻小小小小鳥!哦
class Box{ constructor(num1,num2){ this.num1 = num1; this.num2=num2; } sum(){ return num1+num2; } } var box=new Box(12,88); console.log(box.hasOwnProperty("num1"));//true console.log(box.hasOwnProperty("num2"));//true console.log(box.hasOwnProperty("sum"));//false console.log("num1" in box);//true console.log("num2" in box);//true console.log("sum" in box);//true console.log("say" in box);//false
類的全部實例共享一個原型對象,它們的原型都是Person.prototype,因此proto屬性是相等的ip
class Box{ constructor(num1,num2){ this.num1 = num1; this.num2=num2; } sum(){ return num1+num2; } } //box1與box2都是Box的實例。它們的__proto__都指向Box的prototype var box1=new Box(12,88); var box2=new Box(40,60); console.log(box1.__proto__===box2.__proto__);//true
由此,也能夠經過proto來爲類增長方法。使用實例的proto屬性改寫原型,會改變Class的原始定義,影響到全部實例,因此不推薦使用!
class Box{ constructor(num1,num2){ this.num1 = num1; this.num2=num2; } sum(){ return num1+num2; } } var box1=new Box(12,88); var box2=new Box(40,60); box1.__proto__.sub=function(){ return this.num2-this.num1; } console.log(box1.sub());//76 console.log(box2.sub());//20
class不存在變量提高,因此須要先定義再使用。由於ES6不會把類的聲明提高到代碼頭部,可是ES5就不同,ES5存在變量提高,能夠先使用,而後再定義。
//ES5能夠先使用再定義,存在變量提高 new A(); function A(){ } //ES6不能先使用再定義,不存在變量提高 會報錯 new B();//B is not defined class B{ }