1. 程式人生 > 程式設計 >Js類的構建與繼承案例詳解

Js類的構建與繼承案例詳解

裡類的定義和繼承實在五花八門,所以單獨開一個筆記本記錄。

定義

派生於Object的方式

1.new Object:在建立物件後動態定義屬性、方法
var Car = new Object;
Car.color = "red";
Car.showColor = function(){
	console.log(this.color);
}
//想要繼承就要先構造空物件然後用__proto__原型鏈來繼承
var Car1 = new Object; //或者 = {}
Car1.__proto__ =  Car;

使用函式構造

1.工廠函式:在函式內生成類,好處是不用再構造空物件+繼承原型鏈,直接返回一個物件的複製,類似於建構函式
function createCar(){ //也可以為此函式傳遞引數creatCar(color)
	let car = new Object;
	car.color = "red"; //傳遞引數:car.color = color
	car.showColor = function(){
		console.log(this.color);
	}
	return car;
}

var newCar = createCar(); //傳遞引數:createCar("red")
//但是使用工廠函式,每構造一個函式就會構建一次showColor方法,很不划算
//所以可以在類的工廠函式之前為所有類統一確定一個用於繼承的方法
function showColor(){
	console.log(this.color);
}
function createCar(){
...
	car.showColor = showColor;
...
}

2.建構函式方法:類似於工廠函式方法,使用建構函式方法。不同的是建構函式內屬性只能為this.attr
function Car(color,num){
	this.color = color;
	this.num = num;
	this.showColor = function(){
		console.log(this.color);
	}
	this.drivers = new Array("mike");
}
var car1 = new Car("red",1); //注意,此時Car本身的屬性和方法不能被訪問,只能例項化之						 後訪問
					 //比如:console.log(new Car("red",1).color)
					 //這表示,建構函式真的是類似類的建構函式而非例項化物件,js也					  //有傳統意義的物件而不是隻有函式物件
//和方式1一樣Car的類內函式showColor將在每次構造時被構造出來,佔據了沒必要的空間
var car2 = new Car("green"
,1); car1.drivers.push("kiki"); console.log(car2.drivers); //不存在引用同一個陣列的現象 3.原型方法:類似於Object派生,形成基於Object的原型鏈,再繫結方法和屬性 function Car(){}; Car.prototype.color = "red"; Car.prototype.showColor = function(){ console.log(this.color); } //Car.prototyoe = { //把多個繫結的函式放進一個匿名的類來寫 // mathod1:function(){...}; // mathod2:function(){...}; //} Car.prototype.drivers = new Array("mike","jhon"); var car1 = new Car(); //一定要建立例項才能呼叫方法訪問屬性 var car2 = new Car(); car
1.drivers.push("bill"); console.log(car1.color); console.log(car2.drivers); //這樣繫結arry的屬性全部都指向同一個陣列物件,屬於引用。當改變一個例項的color,所有的color都一起變了

混合方法:

1.建構函式+原型:建構函式內只構造屬性和類內陣列,而用原型的方式宣告類內函式
function Car(color){
	this.color = color;
	this.drivers = new Array("mike");
}
Car.prototype.showColor = function(){
	console.log(this.color);
}
var car1 = new Car(); //一定要建立例項才能呼叫方法訪問屬性
var car2 = new Car();
car1.drivers.push("bill");
console.log(car2.drivers); //避免了原型方法的缺點

2.使用class關鍵字定義類:不能在類外直接定義屬性,仍需要使用prototype方法在類外繫結函式物件。
class Car{
           constructor(color) {
                this.color = color;
           }
           drivers = new Array("mike","jhon");
           hello = function(){
           		return "Di Di"+ this.color; 
           }
           
        }

Car.prototype.hello = function (){ //類外繫結方法
            return "Di Di";
}

var car1 = new Car("red");
var car2 = new Car("green");
car1.drivers.push("kiki");
console.log(car1.color);
console.log(car2.hello());

綜上,當在類內定義變數時,在構造例項時會隨之一起呼叫建構函式進行構造,而類外繫結的方法、屬性將會是一種引用的形式不參與構造直接呼叫。同時,也便於保密,隱藏資訊。

繼承

1.偽裝繼承:把類作為新類的建構函式來繼承,有點神奇,js裡類可以當成函式物件的奇特屬性
function Car1(color){
	this.color = color;
	this.showColor = function(){
		console.log("this car is "+this.color);
	}
	this.drivers = new Array("mike");
}

function Car2(){
	this.makeSound = function(){
		console.log("Di Di");
	}
}

function Car3(color){
	this.newConstruct = Car1; //作為建構函式傳入
	this.newConstruct(color); //呼叫建構函式
	delete this.newConstruct;
	this.newConstruct2 = Car2; //多重繼承,但是由於閉包機制,要用不同的建構函式名
	this.newConstruct2(); 
	delete this.newConstruct2;
}//同樣,偽裝繼承也可以用.prototype來繫結建構函式

var car1 = new Car3("red");
var car2 = new Car3("green");
car1.drivers.push("kiki");
console.log(car1.color);
car1.showColor();
car1.makeSound();
console.log(car2.drivers);

2.用父類的方法call和apply進行繼承
function Car1(color){
	this.color = ceJGXeJUiolor;
	this.showColor = function(){
		console.log("this car is"+this.color);
	}
}
function Car2(num){
	thihttp://www.cppcns.coms.num = num;
	this.makeSound = function(){
		console.log("Di Di");
	}
}

function Car3(color,num){
	Car1.call(this,color);
	Car2.apply(this,augments);//augments為一個數組,包含所需的引數
}

var car1 = new Car3("red",1);
var car2 = new Car3("green",2);
console.log(car1.color);
console.log(car2.num);
car1.showColor();
car1.makeSound();

//也可以把.apply和.call寫在類外,但只能對例項進行操作,不能用於構成類

3.用原型鏈進行繼承:使用__proto__和.prototype構成原型鏈,缺點是不能實現多重繼承,只能通過繫結成建構函式或者再創造幾個類用鏈式方式繼承來來實現多重繼承
function Car1(color){
	this.color = color;
	this.showColor = function(){
		console.log("this car is"+this.color);
	}
}
function Car3(){};
Car3.prototype = new Car1();

4.用class...extends...,也可以實現繼承,但是不能實現多重繼承,也只能像原型鏈一樣用多個類作為節點的方式來實現多重繼承,屬於是ES6的特性了。ES6還引入了let、public、private、protected關鍵字但是不能實現多重繼承,也沒有什麼包的概念也是挺奇葩的
class Car2 extends Car1{
           constructor(color) {
                super(); //類似,super本身可以代表父類,此處是用了代表父類的
                		 //建構函式
                this.color = color;
           }
           drivers = new Array("mike","jhon");
           hello = function(){
           		return "Di Di"+ this.color; 
           }  
        }

5.使用引數可變的封裝函式extend(需要自己實現)實現多個類的按順序繼承extend(A,B,C)的鏈式繼承,B節點繼承A,C繼承B(實際上還是鏈式方式,但是封裝了好理解,是知乎大佬曉巨集和csdn大佬浴盆的答案,https://blog.csdn.net/sysuzhyupeng/article/details/54846949知乎那個寫法不容易理解)。主要還是利用類可以為函式並可作為返回值的特性

所以,正常情況下:建立類用class或者建構函式+原型的方式;繼承類用class...extends...或者call方法。瞭解工廠方法和偽裝繼承。

過載就不細究了,和class一樣不完善,只能自己用augments.length去實現。

到此這篇關於Js類的構建與繼承案例詳解的文章就介紹到這了,更多相關Js類的構建與繼承內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!