老生常談JS中的繼承及實(shí)現(xiàn)代碼
JS雖然不像是JAVA那種強(qiáng)類型的語言,但也有著與JAVA類型的繼承屬性,那么JS中的繼承是如何實(shí)現(xiàn)的呢?
一、構(gòu)造函數(shù)繼承
在構(gòu)造函數(shù)中,同樣屬于兩個(gè)新創(chuàng)建的函數(shù),也是不相等的
function Fn(name){
this.name = name;
this.show = function(){
alert(this.name);
}
}
var obj1 = new Fn("AAA");
var obj2 = new Fn("BBB");
console.log(obj1.show==obj2.show); //false
此時(shí)可以看出構(gòu)造函數(shù)的多次創(chuàng)建會(huì)產(chǎn)生多個(gè)相同函數(shù),造成冗余太多。
利用原型prototype解決。首先觀察prototype是什么東西
function Fn(){}
console.log(Fn.prototype);
//constructor表示當(dāng)前的函數(shù)屬于誰
//__proto__ == [[prototype]],書面用語,表示原型指針
var fn1 = new Fn();
var fn2 = new Fn();
Fn.prototype.show = function(){
alert(1);
}
console.log(fn1.show==fn2.show); //ture
此時(shí),任何一個(gè)對(duì)象的原型上都有了show方法,由此得出,構(gòu)造函數(shù)Fn.prototype身上的添加的方法,相當(dāng)于添加到了所有的Fn身上。
二、call和applay繼承
function Father(skill){
this.skill = skill;
this.show = function(){
alert("我會(huì)"+this.skill);
}
}
var father = new Father("絕世木匠");
function Son(abc){
//這里的this指向函數(shù)Son的實(shí)例化對(duì)象
//將Father里面的this改變成指向Son的實(shí)例化對(duì)象,當(dāng)相遇將father里面所有的屬性和方法都復(fù)制到了son身上
//Father.call(this,abc);//繼承結(jié)束,call適合固定參數(shù)的繼承
//Father.apply(this,arguments);//繼承結(jié)束,apply適合不定參數(shù)的繼承
}
father.show()
var son = new Son("一般木匠");
son.show();
三、原型鏈繼承(demo)
這個(gè)的么實(shí)現(xiàn)一個(gè)一個(gè)簡單的拖拽,a->b的一個(gè)繼承。把a(bǔ)的功能繼承給b。
HTML:
<div id="drag1"></div> <div id="drag2"></div>
CSS:
*{margin: 0;padding: 0;}
#drag1{width: 100px;height: 100px;background: red;position: absolute;}
#drag2{width: 100px;height: 100px;background: black;position: absolute;left: 500px;}
JS:
function Drag(){}
Drag.prototype={
constructor:Drag,
init:function(id){
this.ele=document.getElementById(id);
this.cliW=document.documentElement.clientWidth||document.body.clientWidth;
this.cliH=document.documentElement.clientHeight||document.body.clientHeight;
var that=this;
this.ele.onmousedown=function(e){
var e=event||window.event;
that.disX=e.offsetX;
that.disY=e.offsetY;
document.onmousemove=function(e){
var e=event||window.event;
that.move(e);
}
that.ele.onmouseup=function(){
document.onmousemove=null;
}
}
},
move:function(e){
this.x=e.clientX-this.disX;
this.y=e.clientY-this.disY;
this.x=this.x<0?this.x=0:this.x;
this.y=this.y<0?this.y=0:this.y;
this.x=this.x>this.cliW-this.ele.offsetWidth?this.x=this.cliW-this.ele.offsetWidth:this.x;
this.y=this.y>this.cliH-this.ele.offsetHeight?this.y=this.cliH-this.ele.offsetHeight:this.y;
this.ele.style.left=this.x+'px';
this.ele.style.top=this.y+'px';
}
}
new Drag().init('drag1')
function ChidrenDrag(){}
ChidrenDrag.prototype=new Drag()
new ChidrenDrag().init('drag2')
四、混合繼承
function Father(skill,id){
this.skill = skill;
this.id = id;
}
Father.prototype.show = function(){
alert("我是father,這是我的技能"+this.skill);
}
function Son(){
Father.apply(this,arguments);
}
//如果不做son的原型即成father的原型,此時(shí)會(huì)報(bào)錯(cuò):son.show is not a function
Son.prototype = Father.prototype;
//因?yàn)?,如果不讓son的原型等于father的原型,son使用apply是繼承不到原型上的方法
//但這是一種錯(cuò)誤的原型繼承示例,如果使用這種方式,會(huì)導(dǎo)致修改son原型上的show方法時(shí),會(huì)把father身上的show也修改
//內(nèi)存的堆和棧機(jī)制
Son.prototype.show = function(){
alert("我是son,這是我的技能"+this.skill);
}
var father = new Father("專家級(jí)鐵匠","father");
var son = new Son("熟練級(jí)鐵匠","son");
father.show();
son.show();
上面的示例應(yīng)該修改成以下形式:
以上紅色的代碼應(yīng)改成:
for(var i in Father.prototype){
Son.prototype[i] = Father.prototype[i];
}
//遍歷father的原型身上的所有方法,依次拷貝給son的原型,這種方式稱為深拷貝
這種繼承方式叫做混合繼承,用到了for-in繼承,cell和apple繼承。
五、Es6的class繼承(demo)
這個(gè)demo的功能和原型鏈繼承的demo功能一樣,a->b的繼承
HTML:
<div id="drag1"></div> <div id="drag2"></div>
CSS:
*{margin: 0;padding: 0;}
#drag1{width: 100px;height: 100px;background: red;position: absolute;}
#drag2{width: 100px;height: 100px;background: black;position: absolute;left: 500px;}
JS:
class Drag{
constructor(id){
this.ele=document.getElementById(id);
this.init();
};
init(){
var that=this;
this.ele.onmousedown=function(e){
var e=event||window.event;
that.disX=e.offsetX;
that.disY=e.offsetY;
document.onmousemove=function(e){
var e=event||window.event;
that.move(e);
}
that.ele.onmouseup=function(){
document.onmousemove=null;
that.ele.onmouseup=null;
}
}
};
move(e){
this.ele.style.left=e.clientX-this.disX+"px";
this.ele.style.top=e.clientY-this.disY+"px";
}
}
new Drag("drag1");
class ExtendsDrag extends Drag{
constructor(id){
super(id);
}
}
new ExtendsDrag("drag2")
我總結(jié)的這幾種繼承方法.兩個(gè)demo繼承的方法大家最好在編譯器上跑一下,看看。這樣才能更深刻的去理解。尤其是原型鏈的繼承,js作為一個(gè)面向?qū)ο蟮木幊陶Z言,還是很常用的。
總結(jié)
以上所述是小編給大家介紹的JS中的繼承及實(shí)現(xiàn)代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
使用TypeScript?V8來改進(jìn)您的JavaScript代碼
TypeScript?V8是一個(gè)強(qiáng)大的JavaScript類型系統(tǒng),它可以幫助你發(fā)現(xiàn)JavaScript代碼中的錯(cuò)誤和潛在問題,并在編譯時(shí)捕獲它們,以便您可以解決它們,TypeScript?V8為JavaScript提供一系列的類型注釋,包括自定義類型和其他高級(jí)功能2023-08-08
使用JSX 建立組件 Parser(解析器)開發(fā)的示例
微信小程序封裝網(wǎng)絡(luò)請(qǐng)求和攔截器實(shí)戰(zhàn)步驟
2019 年編寫現(xiàn)代 JavaScript 代碼的5個(gè)小技巧(小結(jié))
JS模擬實(shí)現(xiàn)哈希表及應(yīng)用詳解
JavaScript中Promise的執(zhí)行順序詳解

