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

類和原型的設(shè)計模式之復(fù)制與委托差異

 更新時間:2022年07月06日 15:12:18   作者:掘金安東尼  
這篇文章主要為大家介紹了類和原型的設(shè)計模式之復(fù)制與委托差異詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

小引

JavaScript 技能持有者一定有問過這個問題:

JavaScript 是面向?qū)ο笳Z言嗎?

你期望得到的答案應(yīng)該為:“是” 或 “不是”。

但是可惜,你得不到這樣簡單的答案!

你大概了解一通之后,你會被告知:

JavaScript 不是純粹的面向?qū)ο笳Z言!

wtf!為什么是不純粹?能不能純粹一點(diǎn)?!我們喜歡純粹,不喜歡混沌!

......

實際上,死扣定義真的沒太必要。定義背后的故事才是最重要的!

看完本篇,你就會明白這種“混沌”是什么、來自何處,以及去往何方?。?/p>

撰文不易,多多鼓勵。點(diǎn)贊再看,養(yǎng)成習(xí)慣。??????

“類”設(shè)計模式

婦孺皆知,面向?qū)ο笕筇匦裕骸痉庋b】、【繼承】、【多態(tài)】。

  • 所謂封裝,即把客觀事物封裝成抽象的類。
  • 所謂繼承,即子類繼承父類的能力。
  • 所謂多態(tài),即子類可以用更特殊的行為重寫所繼承父類的通用行為。

其中,“類”的概念最最關(guān)鍵!【類】描述了一種代碼的組織結(jié)構(gòu)形式,它是軟件中對真實世界中問題領(lǐng)域的建模方法。

舉個例子:

就好比我們現(xiàn)實中修房子,你要修一個“寫字樓”、或者一個“居民樓”、或者一個“商場”,你就得分別找到修“寫字樓”、“居民樓”、“商場”的【設(shè)計藍(lán)圖】。

但是設(shè)計藍(lán)圖只是一個建筑計劃,并不是真正的建筑。要想在真實世界實現(xiàn)這個建筑,就得由建筑工人將設(shè)計藍(lán)圖的各類特性(比如長寬高、功能)【復(fù)制】到現(xiàn)實世界來。

這里的【設(shè)計藍(lán)圖】就是【類】,【復(fù)制】的過程就是【實例化】,【實例】就是【對象】。

類的內(nèi)部通常有一個同名的構(gòu)造方法,我們設(shè)想下,它的偽代碼就可能是這樣的:

class Mall { // “商場”類
    Mall( num ){ // 同名構(gòu)造方法
        garage = num // 地下車庫數(shù)量
    }
    shop( goods ) { // 買東西
       output( "We can buy: ", goods )
    }
}
// 構(gòu)造函數(shù)大多需要用 new 來調(diào),這樣語言引擎才知道你想要構(gòu)造一個新的類實例。
vanke = new Mall(1) // vanke 有 1 個地下車庫
vanke.shop("KFC") // "We can buy: KFC"

java 是典型的面向?qū)ο笳Z言?;?ldquo;類”,我們再通過以下一段 java 代碼來看看對繼承和多態(tài)的理解。

public abstract class Animal{ // 抽象類
     abstract void sound();
}
public class Chicken extends Animal{ // 繼承
    public void sound(){
      sound("咯咯咯");
    }
}
public class Duck extends Animal{
    public void sound(){
      sound("嘎嘎嘎");
    }
}
public static void main(String args[]){
  Aninal chicken = new Chicken();
  Animal duck = new Duck();
  chicken.sound(); //咯咯咯
  duck.sound();  //嘎嘎嘎
}

雞和鴨都屬于動物分類,都可以發(fā)出叫聲(繼承),但是它們卻可以發(fā)出不同的叫聲(多態(tài)),很容易理解。

繼承可以使子類獲得父類的全部功能; 多態(tài)可以使程序有良好的擴(kuò)展;

回想下:在 JS 中,我們可能會怎樣寫:

var Duck = function () {};
var Chicken = function () {};
var makeSound = function ( animal ) {
    if( animal instanceof Duck){
        console.log("嘎嘎嘎");    
    }else if( animal instanceof Chicken){
        console.log("咯咯咯");    
    }
};
makeSound(new Duck());
makeSound(new Chicken());

這里既沒用到繼承,也沒用到多態(tài)。這樣【寫判斷】是代碼“不清爽”的罪魁禍?zhǔn)祝?/p>

此處留一個疑問,如果不用判斷,還可以怎么寫?

在 vue2 中,我們可能會這么寫:

export default {
  data() {
      return {
      },
      mounted(){
          this.Chicken()
          this.Duck()
      },
      methods:{
          funtion AnimalSound(sound){
              console.log("叫聲:" + sound)
          },
          funtion Chicken(){
              this.AnimalSound("咯咯咯")
          },
          funtion Duck(){
              this.AnimalSound("嘎嘎嘎")
          }
      }
  }

像這種函數(shù)嵌套調(diào)用是很常見的。沒有看到繼承,也沒有看到多態(tài),甚至都沒有看到最根本的“類”?!

(實際上,每個函數(shù)都是一個 Function 對象。按照最開始定義所述,對象是類的實例,所以也是能在函數(shù)中看到“類”的!)

在 JavaScript 中,函數(shù)成了第一等公民! 函數(shù)似乎什么都能做!它可以返回一個對象,可以賦值給一個變量,可以作為數(shù)組項,可以作為對象的一個屬性......

但這明顯不是“類的設(shè)計模式”吧!

“類的設(shè)計模式” 意味著對【設(shè)計藍(lán)圖】的【復(fù)制】,在 JS 各種函數(shù)調(diào)用的場景下基本看不到它的痕跡。

“原型”設(shè)計模式

其實,眾所周知,JS 也是能做到【繼承】和【多態(tài)】的!只不過它不是通過類復(fù)制的方式,而是通過原型鏈委托的方式!

一圖看懂原型鏈?

看不懂?沒關(guān)系,記住這兩句話再來看:

  • 一個對象的顯示原型的構(gòu)造函數(shù)指向?qū)ο蟊旧恚ê苁煜び袥]有?在本文哪里見過?)
  • 一個對象的隱式原型指向構(gòu)造這個對象的函數(shù)的顯示原型。

原來,JS 不是通過在類里面寫同名構(gòu)造函數(shù)的方式來進(jìn)一步實現(xiàn)的實例化,它的構(gòu)造函數(shù)在原型上!這種更加奇特的代碼服用機(jī)制有異于經(jīng)典類的代碼復(fù)用體系。

這里再附一個經(jīng)典問題?JS new 操作會發(fā)生什么?

會是像類那樣進(jìn)行復(fù)制嗎?

答案是否定的!

JS 訪問一個對象的屬性或方法的時候,先在對象本身中查找,如果找不到,則到原型中查找,如果還是找不到,則進(jìn)一步在原型的原型中查找,一直到原型鏈的最末端。復(fù)制不是它所做的,這種查找的方式才是!對象之間的關(guān)系更像是一種委托關(guān)系,就像找東西,你在我這找不到?就到有委托關(guān)系的其它人那里找找看,再找不到,就到委托委托關(guān)系的人那里找......直至盡頭,最后還找不到,指向 null。

所以:JavaScript 和面向?qū)ο蟮恼Z言不同,它并沒有類來作為對象的抽象模式或者設(shè)計藍(lán)圖。JavaScript 中只有對象,對象直接定義自己的行為。對象之間的關(guān)系是委托關(guān)系,這是一種極其強(qiáng)大的設(shè)計模式。在你的腦海中對象并不是按照父類到子類的關(guān)系垂直組織的,而是通過任意方向的委托關(guān)聯(lián)并排組織的!

不過你也可以通過這種委托的關(guān)系來模擬經(jīng)典的面向?qū)ο篌w系:類、繼承、多態(tài)。但“類”設(shè)計模式只是一種可選的設(shè)計模式,你可以模擬,也可以不模擬!

現(xiàn)實是 ES6 class 給我們模擬了:

class Widget { 
    constructor(width,height) { 
        this.width = width || 50; 
        this.height = height || 50; 
        this.$elem = null; 
    } 
    render($where){ 
        if (this.$elem) { 
            this.$elem.css( { 
                width: this.width + "px", 
                height: this.height + "px" 
            }).appendTo( $where ); 
        } 
    } 
} 
class Button extends Widget { 
    constructor(width,height,label) { 
        super( width, height ); 
        this.label = label || "Default"; 
        this.$elem = $( "<button>" ).text( this.label ); 
    } 
    render($where) { 
        super.render( $where ); 
        this.$elem.click( this.onClick.bind( this ) ); 
    } 
    onClick(evt) { 
        console.log( "Button '" + this.label + "' clicked!" ); 
    } 
}

看起來,非常不錯,很清晰!

沒有 .prototype 顯示原型復(fù)雜的寫法,也無需設(shè)置 .proto 隱式原型。還似乎用 extends 、super 實現(xiàn)了繼承和多態(tài)。

然而,這只是語法糖的陷阱!JS 沒有類,沒有復(fù)制,它的機(jī)制是“委托”。

class 并不會像傳統(tǒng)面向類的語言一樣在申明時作靜態(tài)復(fù)制的行為,如果你有意或者無意修改了父類,那子類也會收到影響。

舉例:

class C { 
 constructor() { 
    this.num = Math.random(); 
 } 
 rand() { 
    console.log( "Random: " + this.num ); 
 } 
} 
var c1 = new C(); 
c1.rand(); // "Random: 0.4324299..."
C.prototype.rand = function() { 
    console.log( "Random: " + Math.round( this.num * 1000 )); 
}; 
var c2 = new C(); 
c2.rand(); // "Random: 867"
c1.rand(); // "Random: 432" ——噢!

ES6 class 混淆了“類設(shè)計模式”和“原型設(shè)計模式&rdquo;。它最大的問題在于,它的語 法有時會讓你認(rèn)為,定義了一個 class 后,它就變成了一個(未來會被實例化的)東西的 靜態(tài)定義。你會徹底忽略 Class 是一個對象,是一個具體的可以直接交互的東西。當(dāng)然,它還有其它細(xì)節(jié)問題,比如屬性覆蓋方法、super 綁定的問題,有興趣自行了解。

總地來說,ES6 的 class 想偽裝成一種很好的語法問題的解決方案,但是實際上卻讓問題更難解決而且讓 JavaScript 更加難以理解。 —— 《你不知道的 JavaScript》

小結(jié)

  • “類設(shè)計模式”的構(gòu)造函數(shù)掛在同名的類里面,類的繼承意味著復(fù)制,多態(tài)意味著復(fù)制 + 自定義。
  • “原型設(shè)計模式”的構(gòu)造函數(shù)掛在原型上,原型的查找是一種自下而上的委托關(guān)系。
  • “類設(shè)計模式”的類定義之后就不支持修改。
  • “原型設(shè)計模式”講究的是一種動態(tài)性,任何對象的定義都可以修改,這和 JavaScript 作為腳本語言所需的動態(tài)十分契合!

你可以用“原型設(shè)計模式”來模擬“類設(shè)計模式”,但是這大概率是得不償失的。

最后,如果再被問道:JavaScript 是面向?qū)ο笳Z言嗎?

如果這篇文章看懂了,就可以圍繞:“類設(shè)計模式”和“原型設(shè)計模式”來吹了。

如果本文沒有看懂,就把下面的標(biāo)答背下來吧......

參考

命名函數(shù)表達(dá)式探秘

函數(shù)式和面向?qū)ο缶幊逃惺裁磪^(qū)別?

tutorials/js.mp

JavaScript 輕量級函數(shù)式編程

你不知道的JavaScript

以上就是類和原型的設(shè)計模式之復(fù)制與委托差異的詳細(xì)內(nèi)容,更多關(guān)于類原型設(shè)計模式復(fù)制委托差異的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 微信小程序 簡單教程實例詳解

    微信小程序 簡單教程實例詳解

    這篇文章主要介紹了微信小程序 簡單教程實例詳解的相關(guān)資料,這里對開發(fā)微信小程序步驟做了一一詳解,需要的朋友可以參考下
    2017-01-01
  • tree?shaking對打包體積優(yōu)化及作用

    tree?shaking對打包體積優(yōu)化及作用

    這篇文章主要為大家介紹了tree?shaking對打包體積優(yōu)化及作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • JavaScript實現(xiàn)文本轉(zhuǎn)換為文件示例詳解

    JavaScript實現(xiàn)文本轉(zhuǎn)換為文件示例詳解

    這篇文章主要為大家介紹了JavaScript實現(xiàn)文本轉(zhuǎn)換為文件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 微信小程序 tabs選項卡效果的實現(xiàn)

    微信小程序 tabs選項卡效果的實現(xiàn)

    這篇文章主要介紹了微信小程序 tabs選項卡效果的實現(xiàn)的相關(guān)資料,微信小程序內(nèi)部組件沒有Tabs 選項卡的功能,自己實現(xiàn)個類似的,需要的朋友可以參考下
    2017-01-01
  • JavaScript策略模式利用對象鍵值的映射關(guān)系詳解

    JavaScript策略模式利用對象鍵值的映射關(guān)系詳解

    這篇文章主要為大家介紹了JavaScript策略模式利用對象鍵值的映射關(guān)系詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 淺談JavaScript作用域

    淺談JavaScript作用域

    這篇文章主要介紹了JavaScript作用域詳情,作用域的使用提高了程序邏輯的局部性,增強(qiáng)了程序的可靠性,減少了名字沖突,下面文章我們一起來了解更多的詳細(xì)內(nèi)容,需要的小伙伴也可以參考一下
    2021-12-12
  • Javascript繼承(上)——對象構(gòu)建介紹

    Javascript繼承(上)——對象構(gòu)建介紹

    Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對象(Object)
    2012-11-11
  • Evil.js項目源碼解讀

    Evil.js項目源碼解讀

    這篇文章主要為大家介紹了最近火爆全網(wǎng)的?Evil.js?源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • JavaScript前端迭代器Iterator與生成器Generator講解

    JavaScript前端迭代器Iterator與生成器Generator講解

    這篇文章主要為大家介紹了JavaScript前端迭代器Iterator與生成器Generator講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • javascript實現(xiàn)超炫的向上滑行菜單實例

    javascript實現(xiàn)超炫的向上滑行菜單實例

    這篇文章主要介紹了javascript實現(xiàn)超炫的向上滑行菜單實現(xiàn)方法,以一個完整實例形式分析了javascript針對頁面元素的遍歷與樣式操作相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08

最新評論

新竹市| 锦屏县| 大田县| 洱源县| 禄丰县| 米脂县| 玉树县| 梁平县| 江达县| 象州县| 饶平县| 汉川市| 鄱阳县| 偏关县| 红河县| 嵊泗县| 台中市| 桓台县| 武乡县| 威海市| 汉沽区| 乐陵市| 前郭尔| 常宁市| 琼结县| 富裕县| 江油市| 景泰县| 阳信县| 子长县| 榆树市| 蓬莱市| 洛隆县| 辽宁省| 日照市| 益阳市| 太原市| 萝北县| 伊春市| 东港市| 闽侯县|