最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript使用原型和原型鏈實現(xiàn)對象繼承的方法詳解

 更新時間:2017年04月05日 10:27:33   作者:番茄與西紅柿  
這篇文章主要介紹了JavaScript使用原型和原型鏈實現(xiàn)對象繼承的方法,簡單講述了javascript原型與原型鏈的原理,并結合實例形式詳細分析了javascript中對象繼承的常見實現(xiàn)技巧,需要的朋友可以參考下

本文實例講述了JavaScript使用原型和原型鏈實現(xiàn)對象繼承的方法。分享給大家供大家參考,具體如下:

實際上JavaScript并不是一門面向對象的語言,不過JavaScript基于原型鏈的繼承方式、函數(shù)式語法,使得編程相當靈活,所以可以利用原型鏈來實現(xiàn)面向對象的編程。

之前對JavaScript一直都是一知半解,這兩天看了一下原型鏈這一塊知識,綜合練習了一下JavaScript的對象繼承方式。

以下就是原型鏈和原型的關系,引用網上的一張圖

在Javascript中,每個函數(shù)都有一個原型屬性prototype指向自身的原型,而由這個函數(shù)創(chuàng)建的對象也有一個proto屬性指向這個原型,而函數(shù)的原型是一個對象,所以這個對象也會有一個proto指向自己的原型,這樣逐層深入直到Object對象的原型,這樣就形成了原型鏈。

- 基本繼承模式

function FatherClass() {
  this.type = 'father';
}
FatherClass.prototype.getTyep = function() {
  console.log(this.type);
}
FatherClass.prototype.obj = {age: 35};
function ChildClass() {
  this.type = 'child';
}
ChildClass.prototype = FatherClass();
ChildClass.prototype.getType = function() {
  console.log(this.type);
}
var father = new FatherClass();
var child = new ChildClass();
father.getTyep();
child.getType();

此方法有優(yōu)點也有缺點,繼承的實現(xiàn)很簡單,代碼簡單容易理解,但是子類繼承父類的成員變量需要自己重新初始化,相當于父類有多少個成員變量,在子類中還需要重新定義及初始化

function FatherClass(type) {
  this.type = type || 'father';
}
function ChildClass(type) {
  this.type = type || 'child';
}
ChildClass.prototype = FatherClass();
ChildClass.prototype.getType = function() {
  console.log(this.type);
}
var father = new FatherClass('fatClass');
var child = new ChildClass('chilClass');

上面這種情況還只是需要初始化name屬性,如果初始化工作不斷增加,這種方式是很不方便的。因此就有了下面一種改進的方式。

- 借用構造函數(shù)

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
Child.prototype = Parent.prototype ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

這樣我們就只需要在子類構造函數(shù)中執(zhí)行一次父類的構造函數(shù),同時又可以繼承父類原型中的屬性,這也比較符合原型的初衷,就是把需要復用的內容放在原型中,我們也只是繼承了原型中可復用的內容。

- 臨時構造函數(shù)模式(圣杯模式)

上面借用構造函數(shù)模式最后改進的版本還是存在問題,它把父類的原型直接賦值給子類的原型,這就會造成一個問題,就是如果對子類的原型做了修改,那么這個修改同時也會影響到父類的原型,進而影響父類對象,這個肯定不是大家所希望看到的。為了解決這個問題就有了臨時構造函數(shù)模式。

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

個人綜合模式

Javascript模式》中到圣杯模式就結束了,可是不管上面哪一種方法都有一個不容易被發(fā)現(xiàn)的問題。大家可以看到我在'Parent'的prototype屬性中加入了一個obj對象字面量屬性,但是一直都沒有用。我們在圣杯模式的基礎上來看看下面這種情況:

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

在上面這種情況中,當我修改child對象obj.a的時候,同時父類的原型中的obj.a也會被修改,這就發(fā)生了和共享原型同樣的問題。出現(xiàn)這個情況是因為當訪問child.obj.a的時候,我們會沿著原型鏈一直找到父類的prototype中,然后找到了obj屬性,然后對obj.a進行修改。再看看下面這種情況:

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

這里有一個關鍵的問題,當對象訪問原型中的屬性時,原型中的屬性對于對象來說是只讀的,也就是說child對象可以讀取obj對象,但是無法修改原型中obj對象引用,所以當child修改obj的時候并不會對原型中的obj產生影響,它只是在自身對象添加了一個obj屬性,覆蓋了父類原型中的obj屬性。而當child對象修改obj.a時,它先讀取了原型中obj的引用,這時候child.obj和Parent.prototype.obj是指向同一個對象的,所以child對obj.a的修改會影響到Parent.prototype.obj.a的值,進而影響父類的對象。AngularJS中關于$scope嵌套的繼承方式就是模范Javasript中的原型繼承來實現(xiàn)的。

根據上面的描述,只要子類對象中訪問到的原型跟父類原型是同一個對象,那么就會出現(xiàn)上面這種情況,所以我們可以對父類原型進行拷貝然后再賦值給子類原型,這樣當子類修改原型中的屬性時就只是修改父類原型的一個拷貝,并不會影響到父類原型。具體實現(xiàn)如下:

var deepClone = function(source,target){
  source = source || {} ;
  target = target || {};
  var toStr = Object.prototype.toString ,
    arrStr = '[object array]' ;
  for(var i in source){
    if(source.hasOwnProperty(i)){
      var item = source[i] ;
      if(typeof item === 'object'){
        target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
        deepClone(item,target[i]) ;
      }else{
        target[i] = item;
      }
    }
  }
  return target ;
} ;
var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : '1'} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
Child.prototype = deepClone(Parent.prototype) ;
var child = new Child('child') ;
var parent = new Parent('parent') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = '2' ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //1

綜合上面所有的考慮,Javascript繼承的具體實現(xiàn)如下,這里只考慮了Child和Parent都是函數(shù)的情況下:

var deepClone = function(source,target){
  source = source || {} ;
  target = target || {};
  var toStr = Object.prototype.toString ,
    arrStr = '[object array]' ;
  for(var i in source){
    if(source.hasOwnProperty(i)){
      var item = source[i] ;
      if(typeof item === 'object'){
        target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
        deepClone(item,target[i]) ;
      }else{
        target[i] = item;
      }
    }
  }
  return target ;
} ;
var extend = function(Parent,Child){
  Child = Child || function(){} ;
  if(Parent === undefined)
    return Child ;
  //借用父類構造函數(shù)
  Child = function(){
    Parent.apply(this,argument) ;
  } ;
  //通過深拷貝繼承父類原型
  Child.prototype = deepClone(Parent.prototype) ;
  //重置constructor屬性
  Child.prototype.constructor = Child ;
} ;

更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數(shù)據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數(shù)學運算用法總結

希望本文所述對大家JavaScript程序設計有所幫助。

相關文章

  • 總結一些js自定義的函數(shù)

    總結一些js自定義的函數(shù)

    總結一些js自定義的函數(shù)...
    2006-08-08
  • JavaScript中的對象和原型(一)

    JavaScript中的對象和原型(一)

    大家都知道在js中沒有類的概念,因此它的對象也與基于類的語言中的對象有所不同。所以大家要了解面向對象,首先要了解js中的對象和原型,下面本文給大家介紹JavaScript中的對象和原型(一)知識,一起看下吧
    2016-08-08
  • 微信小程序對接七牛云存儲的方法

    微信小程序對接七牛云存儲的方法

    本篇文章主要介紹了小程序對接七牛云存儲的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • layui復選框的全選與取消實現(xiàn)方法

    layui復選框的全選與取消實現(xiàn)方法

    今天小編就為大家分享一篇layui復選框的全選與取消實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • javascript獲取元素文本內容的通用函數(shù)

    javascript獲取元素文本內容的通用函數(shù)

    獲取元素文本內容的通用函數(shù),思路很好值得參考。
    2009-12-12
  • 80%應聘者都不及格的JS面試題

    80%應聘者都不及格的JS面試題

    超過80%的候選人對下面這道JS面試題的回答情況連及格都達不到。這究竟是怎樣神奇的一道JS面試題?他考察了候選人的哪些能力?對正在讀本文的你有什么啟示?
    2017-03-03
  • Vuex模塊化應用實踐示例

    Vuex模塊化應用實踐示例

    這篇文章主要介紹了Vuex模塊化應用實踐示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • select、radio表單回顯功能實現(xiàn)避免使用jquery載入賦值

    select、radio表單回顯功能實現(xiàn)避免使用jquery載入賦值

    select、radio表單回顯避免使用jquery載入賦值,最好的做法是:在jsp頁面進行邏輯判斷,具體實現(xiàn)如下,感興趣的朋友可以參考下哈,希望對大家有所幫助
    2013-06-06
  • JS中欺騙詞法作用域的eval和with詳解

    JS中欺騙詞法作用域的eval和with詳解

    詞法作用域就是定義在詞法階段的作用域,如果詞法作用域完全由寫代碼期間函數(shù)所聲明的位置來定義,怎樣才能在運行時來“修改”(也可以說欺騙)詞法作用域呢?JavaScript 中有兩種機制來實現(xiàn)這個目的,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • iframe如何動態(tài)創(chuàng)建及釋放其所占內存

    iframe如何動態(tài)創(chuàng)建及釋放其所占內存

    一個項目后期測試發(fā)現(xiàn)瀏覽器內存一直居高不下,而且打開iframe頁面越多內存占用越大,在IE系列瀏覽器中尤其明顯,下面與大家分享下iframe動態(tài)創(chuàng)建及釋放內存
    2014-09-09

最新評論

长沙县| 理塘县| 沙雅县| 璧山县| 潜江市| 闻喜县| 礼泉县| 柘荣县| 海安县| 永顺县| 曲周县| 遂川县| 武功县| 宕昌县| 漯河市| 呼图壁县| 大田县| 松潘县| 凤阳县| 龙川县| 磴口县| 景谷| 防城港市| 棋牌| 长治市| 孝义市| 朝阳市| 旅游| 木里| 来安县| 赞皇县| 平顶山市| 大荔县| 永善县| 永城市| 锡林郭勒盟| 临武县| 富川| 舞钢市| 苍溪县| 正定县|