每個Web開發人員都應了解的7個JavaScript概念

    JavaScript無處不在。數以百萬計的網頁均基於JavaScript構建,至少目前還沒有出現。一方面,HTML和CSS為網頁提供樣式,另一方面,JavaScript的魔力使您的網頁更加生動。今天,這種語言不僅限於您的Web瀏覽器。您也可以將其用於服務器端應用程序。*在客戶端和服務器端應用程序中使用單一語言不是很酷嗎?*單一的語言可以同時滿足這兩個目的,這是技術行業中的javascript開發人員有大量工作發布的主要原因。

    根據Stack Overflow開發者調查,2019 Javascript是排名第一的編程語言。該語言已被95%的所有網站廣泛使用,您可以在此處查看。無論是小型創業公司還是大型公司,大多數公司都在某種需要這種語言的知識的網站或應用程序上工作。有許多用於javascript的框架和庫。如果您的JavaScript基礎很明確,則可以輕鬆學習這些框架和庫。許多概念使開發人員感到困惑和不知所措,但是對這些概念的深入了解將為您的長期發展提供幫助。框架和庫來來去去,但基本原理始終保持不變。如果基礎很明確,就可以輕鬆構建任何類型的應用程序並學習任何框架和庫。此外,它也將幫助您進行面試。讓我們討論一下javascript的一些基本概念,這對任何javascript開發者來說都是非常重要的。

    1. Scope範圍

    範圍表示變量訪問。運行代碼時我可以訪問什麼變量?默認情況下,在javascript中,您始終處於root作用域,即window作用域。範圍只是一個帶有變量,函數和對象邊界的框。這些邊界對變量施加了限制,並確定您是否有權訪問變量。它將變量的可見性或可用性限制為代碼的其他部分。您必須對這個概念有清楚的了解,因為它可以幫助您在代碼中分離邏輯並提高可讀性。範圍可以通過兩種方式定義:

    • Local Scope允許訪問邊界內的所有內容(在框內)
    • Global Scope 是邊界(框外)之外的所有內容。全局範圍無法訪問在局部範圍內定義的變量,因為它是外部世界封閉的變量,除非您將其返回。

    例:

    下面給出的代碼會給您一個錯誤,因為“名稱”是在showName()函數的邊界(本地範圍)內定義的。您無法在函數外部訪問此變量。

    javascript

    現在,看看下面給出的代碼,看看如何訪問在本地範圍內定義的變量“名稱”。
    訪問局部變量

    2. IIFE(立即調用函數表達式)

    顧名思義,IIFE是javascript中的一個函數,它在定義後立即被調用和執行。外部世界無法訪問在IIFE中聲明的變量,因此可以避免污染全局範圍。因此,使用IIFE的主要原因是立即執行代碼並獲得數據隱私。

    (function () { 
        var name = "Barry";
    })();
    // 無法從外部訪問變量 name
    name // 拋出錯誤:"Uncaught ReferenceError: name is not defined"

    3.Hoisting提升機制

    當對javascript中的Hoisting提升概念不清楚時,許多開發人員會得到意想不到的結果。在javascript中,您可以在定義函數之前調用該函數,並且不會收到錯誤消息“ Uncaught ReferenceError”。這背後的原因是,在代碼執行之前,javascript解釋器總是將變量和函數聲明移至當前作用域(函數作用域或全局作用域)的頂部。讓我們通過示例來了解這一點。

    示例:看下面的代碼。

    function cowSays(sound) {
        console.log(sound);
    }
    
    cowSays('moo');
    cowSays('moo');
    
    function cowSays(sound) {
        console.log(sound);
    }

    二段代碼都輸出:>> moo
    上面的代碼沒有給出錯誤,您在控制台中得到了輸出“ moo”。這是用javascript Hoisting提升機制。

    範例2:

    var a = 5;
    console.log(5);
    輸出:// 5
    a = 5;
    console.log(5);
    var a;
    輸出// 5

    上面帶有提升的代碼將為您提供相同的輸出。

    4.閉包

    閉包只是另一個函數內部的一個函數,可以訪問外部函數變量。現在,這個定義聽起來很簡單,但是真正的魔力是通過scope範圍創建的。內部函數(閉包)可以訪問在其範圍內定義的變量(在其大括號之間定義的變量),在其父函數範圍內的變量以及全局變量。現在,您需要記住,外部函數無法訪問內部函數變量(我們已經在範圍概念中進行了討論)。讓我們舉個例子,以更好的方式理解它。

    const first = () => {
        const greet = 'Hi';
        const second = () => {
            const name = 'john';
            console.log(greet);
        }
    
        return second;
    }
    
    const newFunc = first();
    
    newFunc();

    輸出:Hi

    在上面的示例中,內部函數“ second()”是一個Closure。這個內部函數可以訪問變量“ greet”,它是外部函數“ first()”範圍的一部分。在此,父作用域將無法訪問子作用域變量“name”。

    現在的問題是,為什麼我們需要學習閉包?它有什麼用?當您要將行為(例如,將變量,方法或數組從外部函數擴展到內部函數)時,可以使用閉包。在上面的示例中,second()擴展了函數first()的行為,並且還可以訪問變量“ greet”。

    Javascript不是純粹的面向對象語言,但是您可以通過閉包實現面向對象的行為。在上面的示例中,您可以將const'newFunc'視為具有屬性'greet'和'second()'的對象,就像在OOP語言中一樣。

    在這裡,您需要注意的是,在執行first()語句之後,由於閉包,因此first()函數內部的變量不會被銷毀(即使它具有'return'語句),因為這裡的作用域仍然有效,並且子函數仍然可以訪問父函數的屬性。因此,閉包可以簡單定義為“函數運行,函數執行”。它永遠不會再次執行,但要記住,有對這些變量的引用,因此子作用域始終可以訪問父作用域。”

    5.回調

    在javascript中,回調只是一個函數,該函數作為參數傳遞給另一個函數,並在另一個函數內部調用或執行。在這裡,一個函數需要等待另一個函數執行或返回值,這形成了功能鏈(當X完成,然後執行Y,然後繼續執行)。這就是在JavaScript的異步操作中通常使用回調來提供同步功能的原因。

    例:

    const greeting = (name) => {
        console.log('Hello ' + name);
    }
    
    const processUserName = (callback) => {
        name = 'www.1ju.org';
        callback(name);
    }
    
    processUserName(greeting);

    輸出:

    Hello www.1ju.org

    在上面的示例中,請注意問候語已作為參數(回調)傳遞給'processUserName'函數。在執行“ greeting”功能之前,它等待事件“ processUserName”首先執行。

    6.Promise

    我們了解回調的概念,但是如果您的代碼將在回調內的回調中包含回調並繼續下去,將會發生什麼。好吧,這種回調的遞歸結構稱為“回調地獄”,它有望幫助解決此類問題。當我們需要執行兩個或多個背對背操作(或鏈接回調)時,Promise在異步javascript操作中很有用,其中每個後續函數在前一個函數完成時開始。一個promise是一個對象,它可能在將來的某個時候產生單個值,可能是已解決的值,也可能是未解決(被拒絕)的原因。

    根據developer.mozilla “承諾是代表異步操作最終完成或失敗的對象。本質上,promise是返回的對象,您將在其中附加回調,而不是將回調傳遞到函數中。”

    Promise解決了“回調地獄”的問題,它不過是回調的遞歸結構(回調內的回調等)。
    一個Promise可能處於三種可能的狀態中……

    • Fulfilled已完成:操作成功完成時。
    • Rejected拒絕:操作失敗時。
    • Pending待定:初始狀態,既未實現也不被拒絕。

    讓我們用一個示例討論如何在javascript中創建一個Promise。

    const promise = new Promise((resolve, reject) => {
        isNameExist = true;
        if (isNameExist) {
            resolve("User name exist")
        } else {
            reject("error")
        }
    })
    
    promise.then(result => console.log(result))
    .catch(() => {
        console.log('error !')
    })

    User name exist

    考慮上面的代碼,以作為一個示例Promise的假設,就像異步執行“ isNameExist”操作一樣,在那個promise中,Object參數作為兩個函數來解析和拒絕。如果操作成功,即'isNameExist'為'true',則將解析該錯誤並顯示輸出“ User name exist”,否則該操作將失敗或被拒絕,並顯示結果“ error!”。您可以在將執行第一個操作並將第一個操作的結果傳遞到第二個操作的promise中輕鬆執行鏈接操作,此操作將繼續進行。

    7.Async & Await

    停下來等問題解決,Async & await 並僅在Promises之上等待語法糖,並且像Promise一樣,它還提供了一種更同步地維護異步操作的方法。因此,在javascript中,異步操作可以在各種版本中進行處理...

    • ES5->回調
    • ES6->承諾
    • ES7->異步並等待

    您可以使用Async / await來執行Rest API請求,在該請求中,您希望在將數據推送到視圖之前完全加載數據。對於Nodejs和瀏覽器程序員,async / await是一個很大的語法改進。它可以幫助開發人員使用javascript實現功能編程,還可以提高代碼的可讀性。

    例:

     const showPosts = async () => {
     const response = await fetch('https://jsonplaceholder.typicode.com/posts');
     const posts = await response.json();
     console.log(posts);
    }
    
    showPosts();

    下面是何時在控制台中運行此代碼的圖像。

    async

    為了通知JS我們正在使用Promise,我們需要將'await'包裝在'async'函數中。在上面的示例中,我們(a)wait兩件事:response 響應和發布jason。在將響應轉換為JSON格式之前,我們需要確保已獲取response響應,否則我們最終可能會轉換尚不存在的響應,這很可能會提示錯誤。