主頁 > 前端設計 > JS深入理解閉包/作用域(scope)、作用域鏈/執行背景關系和執行堆疊

JS深入理解閉包/作用域(scope)、作用域鏈/執行背景關系和執行堆疊

2021-10-28 08:08:50 前端設計

前言:JavaScript深入理解scope作用域和閉包,就要先理解什么是執行背景關系和執行堆疊,作用域、作用域鏈、閉包是JavaScript的難點也是重點,其實理解起來也不難,學習過其他語言,比如C語言就可以很好的類比,

一 知識儲備

深入學習JavaScript程式內部的執行機制,就要徹底理解執行背景關系和執行堆疊,

了解一些專業概念

  • EC:函式執行環境(或執行背景關系),Execution Context
  • ECS:執行環境堆疊,Execution Context Stack
  • VO:變數物件,Variable Object
  • AO:活動物件,Active Object
  • scope chain:作用域鏈
二 執行背景關系和執行堆疊
1 什么是執行背景關系?

執行背景關系是評估和執行javascript代碼環境的抽象概念,每當控制器轉到ECMAScript可執行代碼的時候,它都是在執行背景關系中運行,即執行環境中的變數,函式宣告,引數,作用域鏈,this等資訊,

//組成代碼展示
const ExecutionContextObj = {
    VO: window,     // 變數物件
    ScopeChain: {}, // 作用域鏈
    this: window
};
2 執行背景關系三種型別
  • 全域執行背景關系—這是默認背景關系或者說基礎的背景關系,任何不在函式內部的代碼都在全域背景關系中,瀏覽器中的全域物件就是window物件,它會執行兩件事:創建一個全域的 window 物件(瀏覽器的情況下),并且設定 this 的值等于這個全域物件,一個程式中只會有一個全域執行背景關系,

  • 函式執行背景關系—每當一個函式被呼叫時, 都會為該函式創建一個新的背景關系,每個函式都有它自己的執行背景關系,不過是在函式被呼叫時創建的,函式背景關系可以有任意多個,每當一個新的執行背景關系被創建,它會按定義的順序執行一系列步驟,

  • Eval函式執行背景關系—執行在 eval 函式內部的代碼也會有它屬于自己的執行背景關系,JavaScript開發者不經常使用,

3 什么是執行堆疊?

執行堆疊,也叫呼叫堆疊,被用來存盤代碼運行時創建的所有執行背景關系,

堆疊是一種資料結構,遵循后進先出的原則,

當 JavaScript 引擎第一次遇到腳本時,它會創建一個全域的執行背景關系并且壓入當前執行堆疊,每當引擎遇到一個函式呼叫,它會為該函式創建一個新的執行背景關系并壓入堆疊的頂部,引擎會執行那些執行背景關系位于堆疊頂的函式,當該函式執行結束時,執行背景關系從堆疊中彈出,控制流程到達當前堆疊中的下一個背景關系,

function fn1() {
  console.log('fn1被呼叫了 -- 創建了fn1的函式執行背景關系,壓入堆疊');
  fn2(); 
  console.log('fn2執行完成,fn2的執行背景關系會從堆疊中彈出');
}

function fn2() {
  console.log('fn2被呼叫了 -- 創建了fn2的函式執行背景關系,壓入堆疊');
}

fn1();
console.log('fn1執行完成,fn2的執行背景關系會從堆疊中彈出');

運行結果

//fn1被呼叫了 -- 創建了fn1的函式執行背景關系,壓入堆疊
//fn2被呼叫了 -- 創建了fn2的函式執行背景關系,壓入堆疊
//fn2執行完成,fn2的執行背景關系會從堆疊中彈出
//fn1執行完成,fn2的執行背景關系會從堆疊中彈出

在這里插入圖片描述

4 JavaScript引擎創建執行背景關系

執行背景關系有兩個階段

  • 創建階段
  • 執行階段

在代碼執行前是創建階段,發生三件事情

  1. this系結
  2. 創建(LexicalEnvironment)詞法環境組件
  3. 創建(VariableEnvironment)變數環境組件
ExecutionContext = {
  ThisBinding = <this value>,
  LexicalEnvironment = { ... },
  VariableEnvironment = { ... },
}

(1)創建階段

  • this系結

在全域執行背景關系中,this 的值指向全域物件,(在瀏覽器中,this參考window物件)

在函式執行背景關系中,this的指向取決于函式是如何被呼叫的,

let obj = {
    fn: function() {
        console.log(this);
    }
}
let win = obj.fn;
obj.fn(); //this指向obj
win(); // this指向window
  • LexicalEnvironment詞法環境

官方ES6檔案概述:詞法環境是一種規范型別,基于 ECMAScript 代碼的詞法嵌套結構來定義識別符號和具體變數和函式的關聯,一個詞法環境由環境記錄器和一個可能的參考外部詞法環境的空值組成,

attention:識別符號指的是變數/函式的名字,而變數是對實際物件[包含函式型別物件]或原始資料的參考,

詞法環境有兩個組成部分

  1. 宣告式環境記錄器:存盤變數和函式宣告的實際位置
  2. 物件環境記錄器:可以訪問其外部詞法環境(作用域)

詞法環境有兩種型別

全域環境:是一個沒有外部環境的詞法環境,其外部環境參考為 null,擁有一個全域物件(window 物件)及其關聯的方法和屬性(例如陣列方法)以及任何用戶自定義的全域變數,this 的值指向這個全域物件,

函式環境:用戶在函式中定義的變數被存盤在環境記錄中,包含了arguments 物件,對外部環境的參考可以是全域環境,也可以是包含內部函式的外部函式環境,

attention:

在全域環境中,環境記錄器是物件環境記錄器

在函式環境中,環境記錄器是宣告式環境記錄器

  • VariableEnvironment變數環境

在ES6中,詞法環境組件和變數環境組件之間的一個區別是前者用于存盤函式宣告和變數let和const系結,而后者僅用于存盤變數var系結,

(2)執行階段

在此階段,完成對所有這些變數的分配,最后執行代碼,(在執行階段,如果 JavaScript 引擎不能在原始碼中宣告的實際位置找到 let 變數的值,它會被賦值為 undefined

三 作用域(Scope)
1 什么是作用域?

作用域指程式中定義變數的區域,它可以決定當前執行代碼的變數的可訪問權限,按照我自己的理解來說,作用域就是代碼中某些特定的變數、函式在特定的獨立區域可以被訪問到,

舉個例子

        function OutFun() {
            var inVariable = "internal variable";
        }
        OutFun();
        console.log(inVariable);

為什么會報錯呢?這就跟變數的作用域有關系了!這里先不解釋,看完整篇筆記就懂了,

在這里插入圖片描述

2 作用域有什么作用呢?

我們給變數起名字的時候,有時候代碼量太多,一不小心就重名了,就像全世界這么多人,總有很多人重名一個道理,那如何保證識人的唯一性呢,對的!可以通過區域劃分,這些人生活在世界的各個角落,區域是不一樣的,所以我們可以通過A住在B城,另外一個A住在C城,從而把A和A區分開來,作用域也是一個道理,不同作用域下的同名變數不會起沖突的原因就是,重名變數各自在不同的區域被訪問到,起到了隔離的作用,

3 作用域的分類

在ES6之前,JavaScript只有全域作用域函式作用域,在ES6之后,通過提供關鍵字let/const來體現塊級作用域

(1)全域作用域

在代碼中的任何地方都可以被訪問到的物件就擁有全域作用域,那什么情況下是擁有全域作用域的呢?

  • 最外層函式+在最外層函式的外面定義的最外層變數
        var outVariable = "I am outermost variable"; //最外層變數
        function outFun() { //最外層函式
            var innerVariable = "I am internal variable"; //內層變數

            function innerFun() { //內層函式
                console.log(innerVariable);
            }
            innerFun();
        }
        console.log(outVariable);
        outFun();
        console.log(innerVariable);
        innerFun();

在這里插入圖片描述

為什么控制臺會有這樣的列印資訊呢?

在代碼中我們在最外層函式outFun()里面嵌套了一層內層函式innerFun(),變數outVariable在全域作用域有宣告,所以沒有報錯,變數innerVariable在函式內部被宣告,而在全域作用域沒有宣告,所以在全域作用域下取值會報錯,outFun()函式是外層函式,在全域作用域下被宣告被呼叫,不會報錯,innerFun()函式的宣告嵌套在outFun()函式里面,屬于內層函式,在全域作用域呼叫會報錯,要深入理解這些,建議結合計算機組成原理,了解全域變數和區域變數在計算機內部存盤的分配和使用,

  • 未定義直接賦值的變數自動宣告且有全域作用域
        function outFun() {
            variable = "我是沒有被定義直接賦值的變數";
            var invariable = "我是內部變數";
        }
        outFun();
        console.log(variable);
        console.log(invariable);

在這里插入圖片描述

  • 一般情況下,window物件擁有全域作用域
window.name;
window.location;
window.top;

弊端

頻繁使用全域變數在全域作用域起作用,會污染記憶體空間,引起變數重名的沖突,造成資源浪費,全域變數記憶體的分配一直要等到程式執行結束才會被釋放,如果一個變數只需要在代碼第一行使用之后就不會再次被使用,但是它命名到全域作用域,那么這一個全域變數就會污染記憶體空間,一直霸占記憶體位置,但實際上沒有任何的使用價值了,(占著茅坑不拉屎)

解決方案—函式作用域

(2)函式作用域

函式作用域是指宣告在函式內部的變數,和全域作用域相反,是區域作用域,在固定的函式代碼段里面才可以被訪問和使用,函式執行完之后記憶體就會釋放為執行這個函式開辟的記憶體空間,就解決了全域變數會引起污染的問題,

        function Fun() {
            var name = "gaby";

            function SayHi() {
                alert(name);
            }
            SayHi();
        }
        alert(name);
        SayHi();

SayHi()函式是內層函式,嵌套在Fun()外層函式里面,所以會造成腳本錯誤,函式作用域顧名思義就是在函式{}括起來的內部可以被訪問有作用,

在這里插入圖片描述

函式的作用域是分層級的,內層作用域的變數可以訪問外部作用域的變數,反之則不行,

每一個變數都有生命周期

來看代碼例子,加深理解,

        function add1(a) {
            var b = a + a;

            function add2(c) {
                console.log(a, b, c);
            }
            add2(b * 3);          
        }
        add1(2);

根據下圖控制臺的資訊顯示,add2()這個最內層的函式可以依次訪問到變數a,變數b,變數c,

在這里插入圖片描述

給上面的代碼再增加一行,我們再看一下控制臺的資訊,

        function add1(a) {
            var b = a + a;

            function add2(c) {
                console.log(a, b, c);
            }
            add2(b * 3);
            console.log(a, b, c);
        }
        add1(2);

根據下圖控制臺資訊顯示,控制臺報錯了,原因就是add1()這個外層函式不能訪問add2()這個內層函式的變數,

在這里插入圖片描述

在這里插入圖片描述

由上面的例子可以看到,函式變數的訪問順序是按層級劃分的,一層一層查找,

需要注意的是,并不是所有用{}大括號括起來的代碼都是函式作用域,比如回圈if和switch,不會像函式,創建一個新的作用域,

(3)塊級作用域

ES6的新特性,通過let和const關鍵字宣告,所宣告的變數在指定的塊級作用域外無法被訪問,

在什么環境下會被創建呢?

  • 在一個函式內部
  • 在一個代碼塊{}內部

使用let和const的時候需要注意幾個點

(1)宣告的變數不會提升到代碼塊的頂部,需要手動將宣告放置到頂部,方便變數在整個代碼塊內都可以使用

        function getName(condition) {
            if (condition) {
                let name = "gaby";
                return name;
            } else {//name在此處不可用
                return null;
            }
            //name在此處不可用
        }

(2)不能重復宣告同一個變數

        var name = "gaby";
        let name = "gaby";

在這里插入圖片描述

如果一個識別符號在代碼塊內部已經被宣告,那么在這代碼塊內使用let再次宣告會拋出錯誤,name被宣告了兩次,一次是var另一次是let,let不能在同一快作用域內重復宣告一個已經被宣告過的變數,但是如果處理成嵌套的情況,則是可以的,

        var name = "gaby";

        function fun() {
            let name = "gabrielle";
        }

(3)實作for回圈的塊級作用域

計數器變數問題(稍微提一下,這個機理說清楚會需要很大的篇幅)

        for (let i = 0; i < 10; i++) {
            //...
        }
        console.log(i);

使用let宣告i,計數器變數i只在回圈體內能被訪問到,回圈體外找不到,

在這里插入圖片描述

我們再來比較var和let宣告的區別

  • 用var宣告
        var a = [];
        for (var i = 0; i < 10; i++) {
            a[i] = function () {
                console.log(i);
            }
        }
        a[4]();

在這里插入圖片描述

為什么輸出是10?

for回圈里面的i用var宣告,在全域作用域內都可以被訪問,全域變數只有一個i,每執行一次回圈體,i的值都會被改變,回圈體內的陳述句console.log(i)里面的i指向的是全域變數,所有a陣列里面的成員都是指向同一個i,執行完之后都為10,

  • 用let宣告
        var a = [];
        for (let i = 0; i < 10; i++) {
            a[i] = function () {
                console.log(i);
            }
        }
        a[4]();

在這里插入圖片描述

為什么輸出是4?

let和var的作用域不同,let在回圈體的每一輪回圈中有效,每一輪回圈i的值都是不一樣,因為每一輪回圈的i都需要被重新宣告,那每一輪都是新的值,是重復的值還是在上一輪回圈的值基礎上進行計算,**是上一輪回圈的值基礎上進行計算!**這是因為JavaScript引擎會記住上一輪回圈的值,

(4)創造父作用域和子作用域

        for (let i = 0; i < 4; i++) {
            let i = 'gaby';
            console.log(i);
        }

輸出四次gaby,回圈變數i和函式內部i不是同一個作用域,由各自的單獨的作用域,

在這里插入圖片描述

四 作用域鏈
1 自由變數

當前作用域沒有定義的變數叫做自由變數,這個自由變數會由內而外向父級一層一層尋找,

        var a = 1;

        function fun() {
            var b = 2;
            console.log(a);
            console.log(b);
        }
        fun();

在這里插入圖片描述

2 作用域鏈

在自由變數向上一層一層尋找,直到找到全域作用域沒有找到就結束,自由變數一層一層查找的關系,就叫做作用域鏈,

        var a = 1;
        function fun1() {
            var b = 2;

            function fun2() {
                var c = 3;
                console.log(a);
                console.log(b);
                console.log(c);
            }
            fun2();
        }
        fun1();

在這里插入圖片描述

五、閉包

在前面分別整理了要深入理解閉包需要的前綴知識,js原型、原型鏈、繼承+scope作用域、作用域鏈+執行背景關系和執行堆疊+變數的作用域和變數提升等等,在這些前綴知識的基礎上去理解js閉包是不難的,作為一個前端打工人,扎扎實實的js基礎是必要條件,地基不穩樓層又能高到哪里去呢?

1 什么是閉包?

在上一篇筆記中整理了js的scope作用域,不懂回去翻看筆記,能夠訪問其他內部函式變數的函式,成為閉包,

在函式內部定義的函式,被回傳出去并在外部進行呼叫,就是閉包,

        function fun1() {
            var a = 1;

            function fun2() {
                console.log(a);
            }
            return fun2;
        }
        var fn = fun1();
        fn();//形成閉包,從外部獲取內部作用域的資訊,

在這里插入圖片描述
我們再一次回顧一下,前面整理的知識,代碼究竟是怎么樣的一個運行機制?

(1)編譯階段,變數和函式被宣告,作用域就確定下來,

(2)運行函式fun1(),創建fun1()函式的執行背景關系,內部存盤fun1()中所有的變數函式的資訊,

(3)函式fun1()執行完之后,把fun2的參考賦值給外部變數fn,要明確的是此時fn的指標指向的是fun2,此時fn位于全域作用域,fun2位于函式作用域,所以可以看見fn位于fun1() 作用域之外,但是訪問到了fun1()的內部變數,

(4)fn在全域被執行,內部代碼console.log(a)向作用域請求獲取a變數,在本級的作用域沒有找到,就向上父級作用域一層一層找父親(找爸爸),在fun1()找到了a變數,回傳給console.log所以列印出來了1,

2 閉包被創造出來有什么用?

還是一樣的邏輯,一樣方法被創造出來肯定是用來解決問題,那么閉包可以用來干嘛呢?

(1)屬性私有化

接觸過java語言的都學過java可以通過關鍵字public private 設定訪問權限,但是JavaScript中沒有,物件中的方法和屬性均可以訪問到,沒有隱私空間,可以隨意修改屬性和方法,造成安全隱患,想象一下,你的房間沒有鑰匙,任何人都可以進入訪問你的房間,隨意更改你房間的布置,是不是很可怕的事情,閉包的出現就是來解決這個問題的,模擬屬性和方法的私有化,

        function getImformation() {
            var name = "gaby";
            var age = 20;
            return function () {
                return {
                    getName: function () {
                        return name;
                    },
                    getAge: function () {
                        return age;
                    }
                };
            };
        }
        var obj = getImformation()();
        obj.getName();
        obj.getAge();
        obj.age;

在這里插入圖片描述
(2)避免重復實體化

單一實體化,保證一個類只有一個實體,避免污染記憶體空間,先判斷實體是否存在,存在就回傳,不存在創建后回傳,

        function Gaby() {
            this.data = "gaby";
        }
        Gaby.getInstance = (function () {
            var instance;
            return function () {
                if (instance) {
                    return instance;
                } else {
                    instance = new Gaby();
                    return instance;
                }
            }
        })();
        var a = Gaby.getInstance();
        var b = Gaby.getInstance();
        console.log(a === b);
        console.log(a.data);

在這里插入圖片描述

3 閉包會引起什么問題?

JavaScript內部有垃圾回識訓制,用計數的方法 ,當記憶體中的一個變數被參考一次,計數+1,垃圾回識訓制會在固定的時間間隔內詢問這些變數,將計數為0的變數標記為失效變數從而清除釋放記憶體,

再來看第一個閉包代碼,fun1()函式隔絕了外部的影響,所有變數在函式內部完成,fun1()執行后,理論上內部的變數就會被銷毀,記憶體被回收,但是我們寫了一個閉包,這就導致了全域作用域始終存在一個a變數,一直占用記憶體,造成記憶體泄漏,

        function fun1() {
            var a = 1;

            function fun2() {
                console.log(a);
            }
            return fun2;
        }
        var fn = fun1();
        fn();//形成閉包,從外部獲取內部作用域的資訊,

由于閉包使用過度而導致記憶體無法釋放的情況,就叫做記憶體泄漏,

正經一點:記憶體泄露 是指當一塊記憶體不再被應用程式使用的時候,由于某種原因,這塊記憶體沒有返還給作業系統或者記憶體池的現象,記憶體泄漏可能會導致應用程式卡頓或者崩潰,

六、后話

最近也是大三上學期了,也開始到了找實習焦慮的日常,技術崗不缺人才,向上看的人很多,但是愿意向下扎根的人很少,希望每一個coder都能向下扎根也能向上生長,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/339178.html

標籤:其他

上一篇:微信小程式的網上訂餐點餐系統vue_uniapp

下一篇:React組件間通信(常用方式,簡單易用)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more