JS自己是基於面向對象開發的編程語言:因此咱們學習JS主要就是學習類,以及類的實例,在學習類的原型上提供的方法;javascript
類:java
- 封裝、繼承、多態
//=> 在後臺語言中,
public void fn(int x,init y){
}
public void fn(int x){
}
fn(10,20); 執行第一個FN
fn(10); 執行第二個FN
fn('小芝麻'); 報錯
複製代碼
function fn(x, y) {
}
function fn(x) {
}
fn(10, 20); 執行第二個FN
fn(10); 執行第二個FN
複製代碼
function fn(x, y) {
if(y===undefined){
// ...
return;
}
// ....
}
fn(10);
fn(10, 20);
複製代碼
這裏想到了一個笑話:編程
A去醫院檢查,被查出是「類風溼性關節炎」
A:好鬱悶,得了…
B:這個病注意點就行了啊
A:不行,由於咱們打算要孩子
B:你這個病和孩子有啥關係啊
….
10min A的腦子中 "類風溼性關節炎」 => 類是繼承的 複製代碼
在生物學上的繼承相似於:瀏覽器
父親:基因
AAA BBB CCC
兒子:繼承了父親的基因(把父親的部分基因,直接拷貝到自身上)
AAA BBB
兒子基因突變 AAB BBA,可是對父親是沒有影響的
複製代碼
正常的後臺語言中的繼承,就是這種拷貝式的繼承,可是咱們JS中的繼承並非這種繼承;bash
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
this.y = 200;
}
//=> 讓子類的原型等於父類的實例
Child.prototype = new Parent; //=>原型繼承
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
如今c1 能用的方法是:私有的 y 和公有的 getY方法,以及Object上的公有方法;服務器
因此咱們只要讓子類的原型等於父類的實例便可編程語言
- Child.prototype = new Parent
__proto__
原型鏈找到本身定義的屬性和方法「指向/查找」方式的c1.__proto__.xxx = xxx
修改子類原型(原有父類的一個實例)中的內容,內容被修改後,對子類的其餘實例有影響,可是對父類的實例不會有影響函數
c1.__proto__.__proto__.xxx = xxx
直接修改的是父類原型,這樣不只會影響其它父類的實例,也影響其餘子類的實例學習
JS中的重寫影響很大ui
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
// 在子類構造函數中,把父類當作普通方法執行(沒有父類實例,父類原型上的那些東西也就和它不要緊了)
// this -> Child的實例c1
Parent.call(this); // this.x=100 至關於強制給c1這個實例設置一個私有的屬性x,屬性值100,至關於讓子類的實例繼承了父類的私有的屬性,而且也變爲了子類私有的屬性 「拷貝式」
this.y = 200;
}
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
parent(this)
這個 this
是 window
call
強制改變 this
的指向爲 Child
中的 this
Parent.call(this)
this
是當前 Child
中的 this
至關於強制給實例設置了一個私有的屬性,至關於讓子類的實例繼承了父類的私有的屬性,而且也變爲了子類私有的屬性「拷貝式」
咱們滿意的繼承方式應該是:父類私有變爲子類私有 父類公有變爲子類公有
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
Parent.call(this);
this.y = 200;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
那如今咱們只要想辦法讓父類中公有的也能變成子類中公有的便可;
咱們剛纔的原型繼承,大致的實現了這個功能;
Child.prototype.__proto__ === Parent.prototype;
Child.prototype.__proto__ = Parent.prototype;
這樣雖然能實現效果可是IE瀏覽器中不容許咱們操做__proto__
,那咱們有什麼能夠替換它呢?
// Object.create();建立一個空對象,讓其原型鏈指向obj
let obj = {
xxx: 'xxx'
};
console.log(Object.create(obj));
複製代碼
因此能夠寫成:Child.prototype = Object.create(Parent.prototype);
便可
constructor
屬性,因此咱們本身手動加一個默認的;class Parent {
constructor() {
this.x = 100;
}
// Parent.prototype.getX=function...
getX() {
return this.x;
}
}
複製代碼
// 繼承: extends Parent(相似於寄生組合繼承)
// 注意:繼承後必定要在CONSTRUCTOR第一行加上SUPER
class Child extends Parent {
constructor() {
super(); //=>相似於咱們以前的CALL繼承 super(100,200):至關於把Parent中的constructor執行,傳遞了100和200
this.y = 200;
}
getY() {
return this.y;
}
}
let c1 = new Child;
console.log(c1);
// Child(); //=>Uncaught TypeError: Class constructor Child cannot be invoked without 'new' ES6中建立的就是類,不能當作普通函數執行,只能new執行
複製代碼