父類裏有些屬性方法 子類想把父類中的這些屬性方法 繼承過來給子類本身的實例也用用express
( ps: →_→ 能不能專業點 沒文化真可怕 )bash
// 原型鏈繼承:把子類的原型做爲父類的實例
// 子類把父類中的私有和公有 都繼承過來做爲子類的原型屬性(公有的)
function A() {
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
B.prototype = new A; // 將子類 的原型對象 重構爲 父類A的實例
B.prototype.constructor = B;
console.log(B.prototype instanceof A);
console.log(B.prototype.__proto__ === A.prototype);
function B() {
}
var b1 = new B;
var b2 = new B;
console.log(b1);
console.log(b1.a);
console.log(b1.say === b2.say); //這個原型屬性 是從父類的私有屬性中繼承過來的
console.log(B.prototype.__proto__ === A.prototype);
// 多態 子類重寫父類 致使父類中全部實例都會受到影響
B.prototype.__proto__.mess = '已經被子類修改了';
var a1 = new A;
console.log(a1.mess);
複製代碼
// 借用構造函數
// 把父類構造函數當作普通函數執行 將裏面this修改成B類中實例
// 這樣的話父類中this.xxx 就至關於給我子類實例添加私有屬性
// 只能繼承父類中私有屬性
function A() {
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
function B() { // 子類中this 當前實例(子類的實例)
A.call(this); // 把父類構造函數當作普通函數執行 將裏面this修改成B類中實例
}
var b = new B;
console.log(b);
console.log(b.a);
複製代碼
// 組合繼承:原型鏈+借用構造函數繼承
// 原型鏈:把父類私有和公有 都繼承爲子類的公有屬性
// 借用構造函數:只能繼承父類私有屬性
// 組合繼承 缺點
// 1.子類會把父類的實例屬性繼承過來兩組 一組做爲子類實例的私有屬性 一組做爲子類的公有屬性
// 2.父類會被調用倆次
function A() {
console.log(2222);
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
B.prototype = new A; // 繼承父類中原型屬性(繼承公有) 原型鏈繼承是執行一次
B.prototype.constructor = B;
function B() {
A.call(this); // 繼承父類私有的 call繼承時執行一次
}
var b = new B;
console.log(b);
console.log(b.a);
console.log(b.mess);
複製代碼
// 原型式繼承
// Object.create(); 建立一個新對象 而後 讓這個新對象的__proto__指向這個傳遞進來的參數對象
var obj1 = {name: 2, id: 1};
var obj2 = Object.create(obj1); // obj2.__proto__ = obj1;
// console.log(obj2.name);
Object.myCreate = function (o) {
// 建立一個臨時構造函數
function Fn() {
}
// 讓這個臨時構造函數 原型等於傳遞進來的對象
Fn.prototype = o; // A.prototype
return new Fn; // 返回這臨時構造函數的實例 Fn的實例__proto__ = o
};
function A() {
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
// B.prototype = Object.create(A.prototype); // 建立一個新對象(並非直接返回的A類的實例)做爲子類的原型對象 而且這個對象__proto__ = A.prototype;
// 繼承父類公有的屬性 做爲 子類的公有屬性
// 將子類的 原型對象重構爲 這個Fn的實例對象 而且這個實例__proto__ = A.prototype
B.prototype = Object.myCreate(A.prototype);
B.prototype.constructor = B;
function B() {
}
var b = new B;
console.log(b);
複製代碼
// 寄生組合繼承 借用構造函數 + 原型式繼承
// 彌補 組合繼承的缺點
Object.myCreate = function (o) {
function F() {
}
F.prototype = o;
return new F;
};
function A() {
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
// 經過原型式繼承 將父類的 公有屬性 繼承爲子類的公有屬性
// B.prototype = Object.create(A.prototype);
B.prototype = Object.myCreate(A.prototype);
B.prototype.constructor = B;
function B() {
A.call(this); // 將父類的私有屬性繼承爲子類的實例的私有屬性
}
var b = new B;
console.log(b);
複製代碼
// 冒充對象繼承:在子類構造函數中 生成一個父類的實例 而後把父類的實例當作一個普通對象 進行遍歷 將遍歷出來的私有和公有 複製一份 做爲 子類的私有屬性
// 把父類的公有和私有 繼承過來做爲子類的私有屬性
function A() {
this.a = 123;
this.say = function () {
console.log('say');
}
}
A.prototype.mess = 'mess';
function B() {
var temp = new A;
for(var k in temp){
this[k] = temp[k];
}
}
var b = new B;
console.log(b)
複製代碼
// 中間類 IE 屏蔽了
var arr = [11,22,13,14];
arr.shift();
console.log(arr.__proto__ === Array.prototype);
console.log(arr.shift); // 經過arr的原型鏈可以找到這個方法
console.log(arr instanceof Array);
function sum() {
arguments.__proto__ = Array.prototype;
// console.log(arguments instanceof Array);
console.log(arguments.shift());
}
sum(1,34,5,6,5)
複製代碼
class Sub extends Super {
constructor() {
super()
}
}
複製代碼
ES6繼承實際上是 寄生組合式繼承實現,並將子類__proto__ 指向了父類自己函數
"use strict";
// 檢驗當前構造函數是不是經過new關鍵字調用
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
// 實現繼承
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
// 寄生組合繼承
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
// 子類__proto__指向父類
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var Child = function (_Super) {
_inherits(Child, _Super);
function Child() {
_classCallCheck(this, Child);
// call繼承
return _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this));
}
return Child;
}(Super);
複製代碼
ES6方法 設置原型對象 Object.setPrototypeOfui
// 僅適用於Chrome和FireFox,在IE中不工做:
Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
obj.__proto__ = proto;
return obj;
}
複製代碼
Object.create(proto, [propertiesObject]) 建立一個對象 而且這個對象的__proto__指向第一個參數protothis
let obj1 = {id: 1}
let obj2 = Object.create(obj1)
console.log(obj2.__proto__ === obj1) // true
複製代碼