<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 章節導航 [TOC] ### [構造函數有什么問題?](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) 對象構造函數是開始組織代碼的大約一百萬種方法之一。它們在野外很常見,是的JavaScript語言的基本構建塊。 *然而...* 有很多最人*反對*使用構造函數。他們的論點歸結為這樣一個事實:如果你不小心,在使用構造函數時,很容易在代碼中引入錯誤[此](https://tsherif.wordpress.com/2013/08/04/constructors-are-bad-for-javascript/)。文章確實概述了問題的一個相當不錯的工作(擾流警報:作者最終推薦工廠功能) 構造函數的一個最大問題是,它們雖然*看起來*像常規函數,但它們的行為根本不像常規函數。如果嘗試您使用不帶`new`關鍵字的構造函數,則您的程序將無法按預期工作,但它不會生成易于跟蹤的錯誤消息。 主要的內容是,構造雖然不一定者的英文*邪惡的*,但它們不是唯一的方式,它們也可能不是最好的方式。當然,這并不意味著浪費時間了解它們!它們是真實世界代碼中的常見模式,以及您將在網上遇到的許多教程。 ### [工廠功能介紹](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) 工廠函數模式與構造函數類似,工廠但不是函數`new`用于創建33對象,而是在調用函數時簡單地設置并報道查看新對象。看看這個例子。 ~~~javascript const personFactory = (name, age) => { const sayHello = () => console.log('hello!'); return { name, age, sayHello }; }; const jeff = personFactory('jeff', 27); console.log(jeff.name); // 'jeff' jeff.sayHello(); // calls the function and logs 'hello!' ~~~ 供參考,這是使用構造函數模式創建的相同內容: ~~~javascript const Person = function(name, age) { this.sayHello = () => console.log('hello!'); this.name = name; this.age = age; }; const jeff = new Person('jeff', 27); ~~~ #### 對象速記 關于工廠功能示例中第3行的快速說明。2015年,JavaScript中添加了一個用于創建對象的便捷新簡寫。沒有簡寫線3,看起來像這樣: ~~~javascript return {name: name, age: age, sayHello: sayHello} ~~~ 簡而言之,如果您要創建一個對象,其中您指的是與您正在創建的對象屬性具有完全相同名稱的變量,則可以將其壓縮為: ~~~javascript return {name, age, sayHello} ~~~ 有了這些知識,請查看這個小小的黑客: ~~~javascript const name = "Maynard" const color = "red" const number = 34 const food = "rice" // logging all of these variables might be a useful thing to do, // but doing it like this can be somewhat confusing. console.log(name, color, number, food) // Maynard red 34 rice // if you simply turn them into an object with brackets, // the output is much easier to decipher: console.log({name, color, number, food}) // { name: 'Maynard', color: 'red', number: 34, food: 'rice' } ~~~ ### [范圍和結束](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) 從簡單地閱讀上面的例子開始,你可能已經處于很好的狀態,開始在你的代碼中使用工廠函數,但在我們到達那里之前,是時候深入研究一個非常重要的概念:**閉包**。 我們能夠使封閉的意義之前,需要我們確保你有一個*真正*的把握好**范圍**在的JavaScript中。范圍是指代碼中可以使用變量和函數之類的術語。?? 在以下示例中,您知道最后一行會記錄什么嗎? ~~~javascript let a = 17; const func = x => { let a = x; }; func(99); console.log(a); // ??????? ~~~ 是17還是99?你知道為什么嗎?你可以編輯代碼,以便打印其他值嗎? 答案是17,并且它不是99的原因是在第4行,外部變量`a`沒有被重新定義,而是在該函數的范圍內創建了一個*new*`a`。最后,在大多數情況下確定范圍并不是那么復雜,但*對于*理解即將出現的一些更高級的概念*至關重要*,因此請花時間了解以下資源中發生的情況。 1. [視頻這個](https://www.youtube.com/watch?v=SBwoFkRjZvE)簡單明了!從這里開始。 2. [譯者](https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/)從簡單開始,重申視頻所涵蓋的內容,但更深入,更具體地說明了適當的術語。最后,定義他了**閉包***并*描述了**模塊**模式,我們將很快談論這兩種模式。 * 上一篇文章很棒,但有一個不準確的聲明: > JavaScript的的中作用域所有都是`Function Scope`*僅*創建33的,不是它們由`for`或`while`循環或表達式語句創建33的,如`if`或`switch`。新功能=新范圍-這是規則 聲明該*的英文*在當文章寫2013屬實,但ES6亦使不正確。閱讀[這篇](http://wesbos.com/javascript-scoping/)文章以獲得獨家新聞! ### [私有變量和函數](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) 現在我們已經鞏固了您對JavaScript的范圍的了解,請看一下這個例子: ~~~javascript const FactoryFunction = string => { const capitalizeString = () => string.toUpperCase(); const printString = () => console.log(`----${capitalizeString()}----`); return { printString }; }; const taco = FactoryFunction('taco'); printString(); // ERROR!! capitalizeString(); // ERROR!! taco.capitalizeString(); // ERROR!! taco.printString(); // this prints "----TACO----" ~~~ 由于范圍的概念,創建33內部的函數`FactoryFunction`都不能在函數本身之外訪問,這就是上面第9行和第10行失敗的原因。使用其中任何一個函數的唯一方法的英文`return`在對象中使用它們(見第4行),就是這可以我們調用`taco.printString()`但*不能*調用的原因`taco.capitalizeString()`。這里最重要的是,即使*我們*無法訪問該`capitalizeString()`功能,`printString()`也可以。那就是關閉。 閉包的概念是這樣一種想法,即函數保留其范圍,即使它們被傳遞并在該范圍之外調用。在這種情況下,即使在該函數之外調用它,`printString`也可以訪問其中的所有內容`FactoryFunction`。 這是另一個例子: ~~~javascript const counterCreator = () => { let count = 0; return () => { console.log(count); count++; }; }; const counter = counterCreator(); counter(); // 0 counter(); // 1 counter(); // 2 counter(); // 3 ~~~ 在此示例中,`counterCreator`初始化局部變量(`count`)然后返回一個函數。要使用該功能,我們必須將其分配給變量(第9行)。然后,每次我們運行它`console.log`的函數`count`并遞增它。如上所述,函數該`counter`的英文一個閉包。它可以訪問變量,`count`并且可以打印狀語從句:遞增變量,但是我們的程序沒有其他方法可以訪問該變量。 在工廠功能的上下文中,閉包允許我們創建**私有**變量和函數。私有函數是在我們的對象的工作中使用的函數,這些函數不打算在我們的程序中的其他地方使用。換句話說,即使我們的對象可能只做一兩件事,我們也可以自由地將我們的函數拆分起來(允許更干凈,更容易閱讀的代碼),并且只導出程序其余部分的函數將要使用。將這個術語與之前我們的`printString`示例一起使用,`capitalizeString`的英文一個私有函數并且`printString`的英文公共的。 私有函數的概念非常有用,應該盡可能多地使用!對于程序所需的每一項功能,可能會有一些不需要在程序中使用的支持功能。將這些丟失并使其無法訪問會使您的代碼更容易重構,更容易測試,并且更容易為您和想要使用您的對象的任何其他人推理。 ### [返回工廠功能](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) 現在我們已經將理論排除在外,讓我們回到工廠功能。工廠只是簡單的舊的JavaScript函數,它們返回我們在代碼中使用的對象。使用工廠是組織和包含您正在編寫的代碼的有效方式。例如,如果我們正在編寫任何類型的游戲,我們可能會希望對象描述我們的玩家并封裝玩家可以做的所有事情(功能!) ~~~javascript const Player = (name, level) => { let health = level * 2; const getLevel = () => level; const getName = () => name; const die = () => { // uh oh }; const damage = x => { health -= x; if (health <= 0) { die(); } }; const attack = enemy => { if (level < enemy.getLevel()) { damage(1); console.log(`${enemy.getName()} has damaged ${name}`); } if (level >= enemy.getLevel()) { enemy.damage(1); console.log(`${name} has damaged ${enemy.getName()}`); } }; return {attack, damage, getLevel, getName} }; const jimmie = Player('jim', 10); const badGuy = Player('jeff', 5); jimmie.attack(badGuy); ~~~ 花一點時間來看看這個簡單的例子,看看你是否能弄清楚發生了什么。 如果我們試著打電話會發生什么`jimmie.die()`?如果我們試圖操縱健康`jimmie.health -= 1000`怎么辦?當然,這些是我們沒有公開曝光的事情所以我們會收到錯誤。這是一件非常好的事情!設置這樣的對象使我們更容易使用它們,因為我們實際上已經考慮了如何以及何時想要使用這些信息。在這種情況下,我們將jimmie的健康隱藏為對象內部的私有變量,這意味著如果我們想要操作它,我們需要導出一個函數。從長遠來看,這將使我們的代碼*更*容易推理,因為所有邏輯都封裝在適當的位置。 #### 與工廠的繼承 在構造函數課程中,我們深入研究了Prototypes和Inheritance的概念,或者讓我們的對象訪問另一個Object的方法和屬性。使用工廠時,有幾種簡單的方法可以實現這一目標。檢查一下: ~~~javascript const Person = (name) => { const sayName = () => console.log(`my name is ${name}`) return {sayName} } const Nerd = (name) => { // simply create a person and pull out the sayName function! const {sayName} = Person(name) const doSomethingNerdy = () => console.log('nerd stuff') return {sayName, doSomethingNerdy} } const jeff = Nerd('jeff') jeff.sayName() //my name is jeff jeff.doSomethingNerdy() // nerd stuff ~~~ 這種模式*很棒,*因為它允許您選擇要包含在新對象中的函數。如果你想繼續把所有另一個對象放進去,你當然也可以這樣做`Object.assign`(在[這里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)閱讀那個文檔)。 ~~~javascript const Nerd = (name) => { const prototype = Person(name) const doSomethingNerdy = () => console.log('nerd stuff') return Object.assign({}, prototype, {doSomethingNerdy}) } ~~~ * 在繼續之前看看[這篇](https://medium.com/javascript-scene/3-different-kinds-of-prototypal-inheritance-es6-edition-32d777fa16c9)文章。在文章的后半部分,作者介紹了一些我們在這里并沒有真正談論太多的事情,但如果你花一些時間搞清楚他在說什么,你就會得到回報。好東西! ### [模塊模式](https://www.theodinproject.com/courses/javascript/lessons/factory-functions-and-the-module-pattern#null) > 快速旁注:ES6在JavaScript中引入了一個名為“模塊”的新功能。這些本質上是用于在不同JavaScript文件之間導入和導出代碼的語法。它們非常強大,我們將在以后覆蓋它們。但是,它們*不是*我們在這里談論的內容。 模塊實際上與Factory功能非常相似。主要區別在于它們是如何創建的。 認識一個模塊: ~~~javascript const calculator = (() => { const add = (a, b) => a + b; const sub = (a, b) => a - b; const mul = (a, b) => a * b; const div = (a, b) => a / b; return { add, sub, mul, div, }; })(); calculator.add(3,5) // 8 calculator.sub(6,2) // 4 calculator.mul(14,5534) // 77476 ~~~ ?這些概念與工廠函數完全相同,但是,不是創建我們可以反復使用的工廠來創建多個對象,而是模塊模式將工廠包裝在IIFE(立即調用的函數表達式)中。 * 在[本文中](http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html)閱讀有關IIFE的[內容](http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html)。概念很簡單..編寫一個函數,將其包裝在括號中,然后通過添加`()`到函數的末尾立即調用該函數。 在我們的計算器示例中,IIFE內部的函數是一個簡單的工廠函數,就像我們之前定義的那樣,但是我們可以繼續將對象分配給變量,`calculator`因為我們不需要制作大量的計算器,我們只需要一個。就像工廠示例一樣,我們可以擁有任意數量的私有函數和變量,它們保持整齊有序,隱藏在我們的模塊中,只暴露我們實際想要在程序中使用的函數。 將程序的內部工作封裝到對象中的一個有用的副作用是**命名空間**。命名空間是一種用于避免在程序中命名沖突的技術。例如,很容易想象您可以編寫具有相同名稱的多個函數的場景。在我們的計算器示例中,如果我們有一個向HTML顯示添加內容的函數或者在用戶輸入時將數字和運算符添加到堆棧的函數,該怎么辦?可以想象,我們想要調用所有這三個功能`add`,這些功能當然會給我們的程序帶來麻煩。如果人人都被很好地封裝對象的內部,然后我們就沒有煩惱:`calculator.add()`,`displayController.add()`,`operatorStack.add()`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看