類分為 私有屬性 公有屬性 靜態方法
使用物件方式,繼承公有屬性
let obj2 = {
age: 9,
name:'jw'
};
let obj = {
name:'zfpx',
getPName(){ // 可以通過super關鍵字獲取到父屬性
return super.name
},
__proto__:obj2
}
console.log(obj.getPName());
複製程式碼
只繼承公有屬性
Child.prototype.__proto__ = Parent.prototype;
複製程式碼
Object.setPrototypeOf(Child.prototype, Parent.prototype)
複製程式碼
上面兩個等價,一個是es5一個是es6
只繼承共有屬性
Child.prototype = Object.create(Parent.prototype,{constructor:{value:Child}});
let child = new Child;
child.smoking();
console.log(child.constructor);
複製程式碼
實現原理:
function create(parentPrototype,props){
function Fn() {}
Fn.prototype = parentPrototype;
let fn = new Fn();
for(let key in props){
Object.defineProperty(fn, key, {
...props[key],
enumerable:true //不加這句列舉不出來child.constructor(undefined)
});
}
return fn;
}
// defineProperty中加了set get就不能加 writable和value了。
Child.prototype = create(Parent.prototype,{constructor:{value:Child}});
let child = new Child();
console.log(child.constructor);
複製程式碼
只繼承私有屬性 再子類中呼叫父類的方法即可 Parent.call(this)
function Parent(){
this.parent = 'parent';
}
Parent.prototype.smoking = function () {
console.log('吸菸')
}
function Child(){
Parent.call(this)
}
console.log(new Child().parent)
複製程式碼
child繼承父類的所有的屬性
function Parent(){
this.parent = 'parent';
}
Parent.prototype.smoking = function () {
console.log('吸菸')
}
function Child(){}
Child.prototype = new Parent;
let child = new Child();
Child.prototype.eat = function () {
console.log('吃')
}
console.log(child.parent)
console.log(child.smoking)
child.__proto__.eat();
console.log(child.__proto__=== Child.prototype)
console.log(Child.prototype.constructor === Child)
複製程式碼
為了追本溯源, 我順便研究了new運算子具體幹了什麼?發現其實很簡單,就幹了三件事情.
var obj = {};
obj.__proto__ = F.prototype;
F.call(obj);
複製程式碼
第一行,我們建立了一個空物件obj;
第二行,我們將這個空物件的proto成員指向了F函式物件prototype成員物件;
第三行,我們將F函式物件的this指標替換成obj,然後再呼叫F函式.
我們可以這麼理解: 以 new 操作符呼叫建構函式的時候,函式內部實際上發生以下變化:
1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。
2、屬性和方法被加入到 this 引用的物件中。
3、新建立的物件由 this 所引用,並且最後隱式的返回 this
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
// 模擬new
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);//對返回指值做處理,如果是引用物件則返回物件,如果是基本型別則忽略返回值,依然返回物件obj
return typeof ret === 'object' ? ret : obj;
};
var person = objectFactory(Otaku, 'Kevin', '18')
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60
person.sayYourName(); // I am Kevin
複製程式碼
es6中的class繼承公有屬性和私有屬性和靜態方法
class Child extends Parent{ // 要求繼承父親的私有和有公有
constructor(){
super(); // Parent.call(this);
this.age = 9; // 私有屬性
}
static a(){ // 屬於類上的方法
return 1;
}
smoking(){ // 原型上的方法
console.log('smoking')
}
}
let child = new Child();
複製程式碼