繼承:子類繼承父類的屬性和方法:javascript
讓子類的原型指向父類的實例java
B.prototype = new A();
A的實例自己具有父類A的私有屬性和公有方法,子類B的原型指向它,name子類B的實例就能夠找到這些屬性和方法了function A() {
this.x = 100;
};
A.prototype = {
consyructor: A,
getX: function () {
console.log(this.x);
}
};
function B() {
this.y = 200;
};
// function AA() {
// function x() {
// } //先建立一個空對象
// x.prototype = B.prototype; //把父類的原型地址賦值給空對象(即空對象的原型指向父類的原型)
// return new x; // 返回實例
// }
B.prototype = new A; //核心
let f = new B();
複製代碼
new A()
把A做爲類建立它的實例 this:實例
A()
把A做爲普通函數執行 this:window
function A(name) {
// this:f
this.x = name; // f.x=100
};
A.prototype = {
consyructor: A,
getX: function () {
console.log(this.x);//100
}
};
function B(name) {
// this: 實例f
A.call(this,name); //核心 把A執行,讓A中的this變爲f
this.y = name;
};
let f = new B('abc');
console.log(f.x)
複製代碼
B.prototype = new A();
建立的A四位實例雖然指向了A的原型,可是實例中不是空的,存放了A的私有屬性,這些屬性變爲B的公有屬性B.prototype = Object.create(A.prototype);
好處在於咱們是建立一個沒有任何私有屬性的空對象,指向A的原型,這樣B的公有中不會存在A四位私有屬性Object.create()
: 內置Object類天生自帶的方法,
__proto__
指向第一個傳遞進來的對象(把obj做爲新建立空對象的原型)// 原理:
function create(obj){
function AA(){}
let o = new AA;
o.__proto__ = obj;
return o;
}
複製代碼
關於Object.create()數組
let obj = {
name: 'Tom'
};
console.log(Object.create(obj)); //{}
複製代碼
function A() {
// this:f
this.x = 100; // f.x=100
};
A.prototype = {
consyructor: A,
getX: function () {
console.log(this.x);//100
}
};
function B() {
A.call(this); //核心 基於call繼承,把A的私有變爲B的私有 f.x=100
this.y = 200;
};
// B.prototype = A.prototype; //通常不這樣處理,由於這種模式能夠輕易修改父類A原型上的東西(重寫),這樣會致使A的其餘實例受到影響
B.prototype = Object.create(A.prototype);
let f = new B();
console.log(f.x)
複製代碼
子類.call(this)
=> 繼承父類的私有屬性子類.prototype = Object.create(父類.prototype)
=> 繼承父類的公有方法子類.__proto__
指向父類(本來,類.__proto__ = Function.prototype
)//ES6 class繼承
class A {
constructor() {
console.log(arguments); //Tom 子類的實例把參數傳遞給子類的構造函數,
this.name = arguments;
this.x = 100;
}
getX() {
console.log(this.x);
}
}
class B extends A{//相似與實現了原型繼承
constructor(){
super(...arguments)
//super相似於call繼承,在這裏至關於把父類的constructor執行,而且讓方法中的this是B的實例,super當中傳遞的實參都是給A的
this.y = 200;
console.log(...arguments)
}
getY (){
console.log(this.y);
}
}
let f = new B('Tom','Jerry');
console.dir(f);
複製代碼
關於class語法:函數
class Fn { //Fn是類名,沒有小括號
constructor(n, m) {
// super();
//=> 等價於傳統ES5中類的構造體
this.x = n;
this.y = m;
}
//=> 給Fn的原型上設置方法(只能設置方法不能設置屬性)
getX() {
console.log(this.x);
}
//設置靜態方法:把Fn當作一個普通對象設置的私有方法(和實例沒有關係),一樣也只能設置方法不能寫屬性
static AA(){
console.log(3)
}
}
let f = new Fn(10,20);
console.log(f.x); //10
f.getX(); //10
Fn.AA(); //3
複製代碼
B.prototype = {...A.prototype}
prototype
複製一份給子類(把地址賦值給子類)function A (){
this.name = 'Tom';
};
A.prototype.getX = function(){
console.log(this.name);
}
function B(){
A.call(this);
this.age = 18
}
B.prototype = {...A.prototype};
let f = new B();
console.log(f); //B {name: "Tom", age: 18} age: 18 name: "Tom" __proto__:getX: ƒ () __proto__: Object
複製代碼
function A() {
this.name = 'Tom';
};
A.prototype.getX = function () {
console.log(this.name);
}
function B() {
A.call(this);
this.age = 18
}
B.prototype = deepClone(A.prototype); //將父類的原型上的屬性和方法克隆一份 複製地址給子類
let f = new B();
console.log(f);
function deepClone(obj) {
//先聲明一個數組,去存克隆出來的內容
//判斷obj是否爲數組,是數組就o就爲[],不然爲{}
let o = obj.push ? [] : {};
//循環傳進來的對象
for (let attr in obj) {
//檢測對象中各項是否爲該對象的私有屬性,true則執行下面的代碼
//判斷對象中的某個值是否爲引用類型
//若是是,就繼續調用deepClone把引用值傳到函數中
if (obj.hasOwnProperty(attr)) {
if (typeof obj[attr] === 'object') {
o[attr] = deepClone(obj[attr])
} else {
//若是是簡單類型就直接賦值
o[attr] = obj[attr];
}
}
}
return o;
}
複製代碼
====ui
我的認爲,this