中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript中有哪些繼承形式

發布時間:2021-04-08 15:18:04 來源:億速云 閱讀:331 作者:Leah 欄目:web開發

本篇文章為大家展示了javascript中有哪些繼承形式,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

Js的繼承大體上就是兩種:對象冒充、原型方式。這兩種方式各有優點和缺陷,這里我先列舉出來,再從底層分析區別:

(一)對象冒充

function A(name){
this.name = name;
this.sayHello = function(){alert(this.name+” say Hello!”);};
}
function B(name,id){
this.temp = A;
this.temp(name); //相當于new A();
delete this.temp; //防止在以后通過temp引用覆蓋超類A的屬性和方法
this.id = id;
this.checkId = function(ID){alert(this.id==ID)};
}

當構造對象B的時候,調用temp相當于啟動A的構造函數,注意這里的上下文環境中的this對象是B的實例,所以在執行A構造函數腳本時,所有A的變量 和方法都會賦值給this所指的對象,即B的實例,這樣子就達到B繼承了A的屬性方法的目的。

之后刪除臨時引用temp,是防止維護B中對A的類對象(注 意不是實例對象)的引用更改,因為更改temp會直接導致類A(注意不是類A的對象)結構的變化。

我們看到了,在Js版本更新的過程中,為了更方便的執行這種上下文this的切換以達到繼承或者更加廣義的目的,增加了call和apply函數。它們的 原理是一樣的,只是參數不同的版本罷了(一個可變任意參數,一個必須傳入數組作為參數集合)。這里就以call為例子,解釋一下用call實現的對象冒充 繼承。

function Rect(width, height){
this.width = width;
this.height = height;
this.area = function(){return this.width*this.height;};
}
function myRect(width, height, name){
Rect .call(this,width,height);
this.name = name;
this.show = function(){
alert(this.name+” with area:”+this.area());
}
}

關于Call方法,官方解釋:調用一個對象的一個方法,以另一個對象替換當前對象。

call (thisOb,arg1, arg2…)

這也是一種對象冒充的繼承,其實在call方法調用的時候發生的事情也是上下文環境變量this的替換,在myRect函數體中this肯定是指向類 myRect對象的實例了,然而用這個this作為上下文環境變量調用名字叫Rect方法,即類Rect的構造函數。

于是此時調用Rect時候對this 的賦值屬性和方法都實際上是對一個myRect的對象進行。所以說盡管call和apply并不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。

對象冒充繼承就是這么一回事,它可以實現多重繼承,只要重復做這一套賦值的流程就可以了。不過目前真正大規模使用得并不多,為什么呢?

因為它有一個明顯的 性能缺陷,這就要說道OO的概念了,我們說對象是成員+成員方法的集合,構造對象實例的時候,這些實例只需要擁有各自的成員變量就可以了,成員方法只是一 段對變量操作的可執行文本區域而已,這段區域不用為每個實例而復制一份,所有的實例都可以共享。

現在回到Js利用對象冒充模擬的繼承里,所有的成員方法都 是針對this而創建的,也就是所所有的實例都會擁有一份成員方法的副本,這是對內存資源的一種極度浪費。

其它的缺陷比如說對象冒充無法繼承 prototype域的變量和方法就不用提了,筆者認為前一個致命缺陷就已經足夠。不過,我們還是需要理解它,特別是父類的屬性和方法是如何繼承下來的原 理,對于理解Js繼承很重要。

【推薦學習:javascript高級教程】

(二)原型方式

第二種繼承方式是原型方式,所謂原型方式的繼承,是指利用了prototype或者說以某種方式覆蓋了prototype,從而達到屬性方法復制的目的。 其實現方式有很多中,可能不同框架多少會有一點區別,但是我們把握住原理,就不會有任何不理解的地方了。看一個例子(某一種實現):

function Person(){
this.name = “Mike”;
this.sayGoodbye = function(){alert(“GoodBye!”);};
}
Person.prototype.sayHello = function(){alert(”Hello!”);};
function Student(){}
Student.prototype = new Person();

關鍵是對最后一句Student原型屬性賦值為Person類構造的對象,這里筆者解釋一下父類的屬性和方法是如何copy到子類上的。

Js對象在讀取某個對象屬性的時候,總是先查看自身域的屬性列表,如果有就返回否則去讀取prototype域,如果找到就返回,由于prototype可以指向別的對象,所以Js解釋器會遞歸的去查找prototype域指向對象的prototype域,直到prototype為本身就停止,此時還沒找到就成undefined了。

這樣看來,最后一句發生的效果就是將父類所有屬性和方法連接到子類的prototype域上,這樣子類就繼承了父類所有的屬性和方法,包括name、 sayGoodbye和sayHello。這里與其把最后一句看成一種賦值,不如理解成一種指向關系更好一點。

這種原型繼承的缺陷也相當明顯,就是繼承時 父類的構造函數時不能帶參數,因為對子類prototype域的修改是在聲明子類對象之后才能進行,用子類構造函數的參數去初始化父類屬性是無法實現的, 如下所示:

function Person(name){
this.name = name;
}
function Student(name,id){
this.id = id;
}
Student.prototype = new Person(this.name);

兩種繼承方式已經講完了,如果我們理解了兩種方式下子類如何把父類的屬性和方法“抓取”下來,就可以自由組合各自的利弊,來實現真正合理的Js繼承。下面是個人總結的一種綜合方式:

function Person(name){
this.name = name;
}
Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);};
function Student(name,id){
Person.call(this,name);
this.id = id;
}
Student.prototype = new Person();
Student.prototype.show = function(){
alert(“Name is:”+ this.name+” and Id is:”+this.id);

上述內容就是javascript中有哪些繼承形式,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

根河市| 甘谷县| 惠水县| 宿迁市| 岳西县| 吉木萨尔县| 怀集县| 正镶白旗| 左贡县| 天台县| 裕民县| 东乡族自治县| 上栗县| 叶城县| 津南区| 东辽县| 铜鼓县| 大新县| 尼玛县| 丹凤县| 剑川县| 林周县| 浦北县| 泰安市| 大田县| 新沂市| 阜南县| 南皮县| 大荔县| 铜梁县| 苏尼特左旗| 宝清县| 华坪县| 长宁区| 昂仁县| 孙吴县| 贵定县| 新营市| 奉化市| 阳西县| 华池县|