記錄--關於【前端高級技巧】九個問題鞏固知識

来源:https://www.cnblogs.com/smileZAZ/archive/2022/09/29/16742247.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 第一問:安全類型檢測——typeof和instanceof 區別以及缺陷,以及解決方案 這兩個方法都可以用來判斷變數類型 區別:前者是判斷這個變數是什麼類型,後者是判斷這個變數是不是某種類型,返回的是布爾值 (1)typeof 缺陷: 1 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

第一問:安全類型檢測——typeof和instanceof 區別以及缺陷,以及解決方案

這兩個方法都可以用來判斷變數類型

區別:前者是判斷這個變數是什麼類型,後者是判斷這個變數是不是某種類型,返回的是布爾值

(1)typeof

缺陷:

1.不能判斷變數具體的數據類型比如數組、正則、日期、對象,因為都會返回object,不過可以判斷function,如果檢測對象是正則表達式的時候,在Safari和Chrome中使用typeof的時候會錯誤的返回"function",其他的瀏覽器返回的是object.

2.判斷null的時候返回的是一個object,這是js的一個缺陷,判斷NaN的時候返回是number

(2)instanceof 可以用來檢測這個變數是否為某種類型,返回的是布爾值,並且可以判斷這個變數是否為某個函數的實例,它檢測的是對象的原型

let num = 1
num instanceof Number // false


num = new Number(1)
num instanceof Number // true

明明都是num,而且都是1,只是因為第一個不是對象,是基本類型,所以直接返回false,而第二個是封裝成對象,所以true。

這裡要嚴格註意這個問題,有些說法是檢測目標的__proto__與構造函數的prototype相同即返回true,這是不嚴謹的,檢測的一定要是對象才行,如:

let num = 1
num.__proto__ === Number.prototype // true
num instanceof Number // false

num = new Number(1)
num.proto === Number.prototype // true
num instanceof Number // true

num.proto === (new Number(1)).proto // true

此外,instanceof還有另外一個缺點:如果一個頁面上有多個框架,即有多個全局環境,那麼我在a框架里定義一個Array,然後在b框架里去用instanceof去判斷,那麼該array的原型鏈上不可能找到b框架里的array,則會判斷該array不是一個array。

解決方案:使用Object.prototype.toString.call(value) 方法去調用對象,得到對象的構造函數名。可以解決instanceof的跨框架問題,缺點是對用戶自定義的類型,它只會返回[object Object]

第二問:既然提到了instanceof,那手寫實現下instanceof吧

// [1,2,3] instanceof Array ---- true

// L instanceof R
// 變數R的原型 存在於 變數L的原型鏈上
function instance_of(L,R){    
    // 驗證如果為基本數據類型,就直接返回false
    const baseType = ['string', 'number','boolean','undefined','symbol']
    if(baseType.includes(typeof(L))) { return false }
    
    let RP  = R.prototype;  //取 R 的顯示原型
    L = L.__proto__;       //取 L 的隱式原型
    while(true){           // 無線迴圈的寫法(也可以使 for(;;) )
        if(L === null){    //找到最頂層
            return false;
        }
        if(L === RP){       //嚴格相等
            return true;
        }
        L = L.__proto__;  //沒找到繼續向上一層原型鏈查找
    }
}

第三問:作用域安全的構造函數--當我們new一個構造函數的時候可以獲得一個實例,要是我們忘記寫new了呢?

例如

function Person(){
    this.name = "小紅"
}


p = Person();

這會發生什麼問題?,怎麼解決

這樣直接使用,this會映射到全局對象window上。解決方法可以是:首先確認this對象是正確類型的實例。如果不是,那麼會創建新的實例並返回。請看下麵的例子

function Person(){
    if(this instanceof Person){
        this.name = "小紅"
    }else{
        return  new Person()
    }
}


p = Person();

第四問:談一下惰性載入函數

在JavaScript代碼中,由於瀏覽器之間行為的差異,多數JavaScript代碼包含了大量的if語句,以檢查瀏覽器特性,解決不同瀏覽器的相容問題。例如添加事件的函數:

function addEvent (element, type, handler) {
    if (element.addEventListener) {
        element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + type, handler);
    } else {
        element["on" + type] = handler;
    }
}
每次調用addEvent()的時候,都要對瀏覽器所支持的能力仔細檢查。首先檢查是否支持addEventListener方法,如果不支持再檢查是否支持attachEvent方法,如果還不支持,就用DOM 0級的方法添加事件。在調用addEvent()過程中,每次這個過程都要走一遍。其實,瀏覽器支持其中的一種方法就會一直支持他,就沒有必要再進行其他分支的檢測了,也就是說if語句不必每次都執行,代碼可以運行的更快一些。解決的方案稱之為惰性載入。 所謂惰性載入,就是說函數的if分支只會執行一次,之後調用函數時,直接進入所支持的分支代碼。有兩種實現惰性載入的方式,第一種事函數在第一次調用時,對函數本身進行二次處理,該函數會被覆蓋為符合分支條件的函數,這樣對原函數的調用就不用再經過執行的分支了,我們可以用下麵的方式使用惰性載入重寫addEvent()。
function addEvent (type, element, handler) {
    if (element.addEventListener) {
        addEvent = function (type, element, handler) {
            element.addEventListener(type, handler, false);
        }
    }
    else if(element.attachEvent){
        addEvent = function (type, element, handler) {
            element.attachEvent('on' + type, handler);
        }
    }
    else{
        addEvent = function (type, element, handler) {
            element['on' + type] = handler;
        }
    }
    return addEvent(type, element, handler);
}

在這個惰性載入的addEvent()中,if語句的每個分支都會為addEvent變數賦值,有效覆蓋了原函數。最後一步便是調用了新賦函數。下一次調用addEvent()的時候,便會直接調用新賦值的函數,這樣就不用再執行if語句了。

第二種實現惰性載入的方式是在聲明函數時就指定適當的函數。這樣在第一次調用函數時就不會損失性能了,只在代碼載入時會損失一點性能。一下就是按照這一思路重寫的addEvent()。

var addEvent = (function () {
    if (document.addEventListener) {
        return function (type, element, fun) {
            element.addEventListener(type, fun, false);
        }
    }
    else if (document.attachEvent) {
        return function (type, element, fun) {
            element.attachEvent('on' + type, fun);
        }
    }
    else {
        return function (type, element, fun) {
            element['on' + type] = fun;
        }
    }
})();

這個例子中使用的技巧是創建一個匿名的自執行函數,通過不同的分支以確定應該使用那個函數實現,實際的邏輯都一樣,不一樣的地方就是使用了函數表達式(使用了var定義函數)和新增了一個匿名函數,另外每個分支都返回一個正確的函數,並立即將其賦值給變數addEvent。

惰性載入函數的優點只執行一次if分支,避免了函數每次執行時候都要執行if分支和不必要的代碼,因此提升了代碼性能,至於那種方式更合適,就要看您的需求而定了。

第五問:談一下函數節流

概念:限制一個函數在一定時間內只能執行一次。

主要實現思路 就是通過 setTimeout 定時器,通過設置延時時間,在第一次調用時,創建定時器,先設定一個變數true,寫入需要執行的函數。第二次執行這個函數時,會判斷變數是否true,是則返回。當第一次的定時器執行完函數最後會設定變數為false。那麼下次判斷變數時則為false,函數會依次運行。目的在於在一定的時間內,保證多次函數的請求只執行最後一次調用。

函數節流的代碼實現

function throttle(fn,wait){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                fn.apply(context,args);
                timer = null;
            },wait)
        }
    }
}


function handle(){
console.log(Math.random());
}

window.addEventListener("mousemove",throttle(handle,1000));

函數節流的應用場景(throttle)

  • DOM 元素的拖拽功能實現(mousemove)
  • 高頻點擊提交,表單重覆提交
  • 搜索聯想(keyup)
  • 計算滑鼠移動的距離(mousemove)
  • 監聽滾動事件,比如是否滑到底部自動載入更多,用throttle來判斷
  • 射擊游戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈)
  • 監聽滾動事件判斷是否到頁面底部自動載入更多:給 scroll 加了 debounce 後,只有用戶停止滾動後,- - 才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次.

第六問:談一下函數防抖

概念:函數防抖(debounce),就是指觸發事件後,在 n 秒內函數只能執行一次,如果觸發事件後在 n 秒內又觸發了事件,則會重新計算函數延執行時間。

函數防抖的要點,是需要一個 setTimeout 來輔助實現,延遲運行需要執行的代碼。如果方法多次觸發,則把上次記錄的延遲執行代碼用 clearTimeout 清掉,重新開始計時。若計時期間事件沒有被重新觸發,等延遲時間計時完畢,則執行目標代碼。

函數防抖的代碼實現

function debounce(fn,wait){
    var timer = null;
    return function(){
        if(timer !== null){
            clearTimeout(timer);
        }
        timer = setTimeout(fn,wait);
    }
}
    
function handle(){
    console.log(Math.random());
}
    
window.addEventListener("resize",debounce(handle,1000));

函數防抖的使用場景 函數防抖一般用在什麼情況之下呢?一般用在,連續的事件只需觸發一次回調的場合。具體有:

  • 搜索框搜索輸入。只需用戶最後一次輸入完,再發送請求;
  • 用戶名、手機號、郵箱輸入驗證;
  • 瀏覽器視窗大小改變後,只需視窗調整完後,再執行 resize 事件中的代碼,防止重覆渲染。

目前遇到過的用處就是這些,理解了原理與實現思路,小伙伴可以把它運用在任何需要的場合,提高代碼質量。

第七問:談一下requestAnimationFrame

動畫原理 : 眼前所看到圖像正在以每秒60次的頻率刷新,由於刷新頻率很高,因此你感覺不到它在刷新。而動畫本質就是要讓人眼看到圖像被刷新而引起變化的視覺效果,這個變化要以連貫的、平滑的方式進行過渡。 那怎麼樣才能做到這種效果呢?

刷新頻率為60Hz的屏幕每16.7ms刷新一次,我們在屏幕每次刷新前,將圖像的位置向左移動一個像素,即1px。這樣一來,屏幕每次刷出來的圖像位置都比前一個要差1px,因此你會看到圖像在移動;由於我們人眼的視覺停留效應,當前位置的圖像停留在大腦的印象還沒消失,緊接著圖像又被移到了下一個位置,因此你才會看到圖像在流暢的移動,這就是視覺效果上形成的動畫。

與setTimeout相比較

理解了上面的概念以後,我們不難發現,setTimeout 其實就是通過設置一個間隔時間來不斷的改變圖像的位置,從而達到動畫效果的。但我們會發現,利用seTimeout實現的動畫在某些低端機上會出現卡頓、抖動的現象。 這種現象的產生有兩個原因:

  • setTimeout的執行時間並不是確定的。在Javascript中, setTimeout 任務被放進了非同步隊列中,只有當主線程上的任務執行完以後,才會去檢查該隊列里的任務是否需要開始執行,因此 setTimeout 的實際執行時間一般要比其設定的時間晚一些。

  • 刷新頻率受屏幕解析度和屏幕尺寸的影響,因此不同設備的屏幕刷新頻率可能會不同,而 setTimeout只能設置一個固定的時間間隔,這個時間不一定和屏幕的刷新時間相同。

以上兩種情況都會導致setTimeout的執行步調和屏幕的刷新步調不一致,從而引起丟幀現象

requestAnimationFrame:與setTimeout相比,requestAnimationFrame最大的優勢是由系統來決定回調函數的執行時機。具體一點講,如果屏幕刷新率是60Hz,那麼回調函數就每16.7ms被執行一次,如果刷新率是75Hz,那麼這個時間間隔就變成了1000/75=13.3ms,換句話說就是,requestAnimationFrame的步伐跟著系統的刷新步伐走。它能保證回調函數在屏幕每一次的刷新間隔中只被執行一次,這樣就不會引起丟幀現象,也不會導致動畫出現卡頓的問題。

除此之外,requestAnimationFrame還有以下兩個優勢:

  • CPU節能:使用setTimeout實現的動畫,當頁面被隱藏或最小化時,setTimeout 仍然在後臺執行動畫任務,由於此時頁面處於不可見或不可用狀態,刷新動畫是沒有意義的,完全是浪費CPU資源。而requestAnimationFrame則完全不同,當頁面處理未激活的狀態下,該頁面的屏幕刷新任務也會被系統暫停,因此跟著系統步伐走的requestAnimationFrame也會停止渲染,當頁面被激活時,動畫就從上次停留的地方繼續執行,有效節省了CPU開銷。

  • 函數節流:在高頻率事件(resize,scroll等)中,為了防止在一個刷新間隔內發生多次函數執行,使用requestAnimationFrame可保證每個刷新間隔內,函數只被執行一次,這樣既能保證流暢性,也能更好的節省函數執行的開銷。一個刷新間隔內函數執行多次時沒有意義的,因為顯示器每16.7ms刷新一次,多次繪製並不會在屏幕上體現出來。

第八問:web計時,你知道該怎麼計算首屏,白屏時間嗎?

白屏時間: 白屏時間指的是瀏覽器開始顯示內容的時間。因此我們只需要知道是瀏覽器開始顯示內容的時間點,即頁面白屏結束時間點即可獲取到頁面的白屏時間。

 計算白屏時間 因此,我們通常認為瀏覽器開始渲染 標簽或者解析完 標簽的時刻就是頁面白屏結束的時間點。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>白屏</title>
  <script type="text/javascript">
    // 不相容performance.timing 的瀏覽器,如IE8
    window.pageStartTime = Date.now();
  </script>
  <!-- 頁面 CSS 資源 -->
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
  <script type="text/javascript">
    // 白屏時間結束點
    window.firstPaint = Date.now();
  </script>
</head>
<body>
  <!-- 頁面內容 -->
</body>
</html>

因此白屏時間則可以這樣計算出:

可使用 Performance API 時:

白屏時間 = firstPaint - performance.timing.navigationStart;

不可使用 Performance API 時:

白屏時間 = firstPaint - pageStartTime; //雖然我們知道這並不准確,畢竟DNS解析,tcp三次握手等都沒計算入內。

首屏時間: 首屏時間是指用戶打開網站開始,到瀏覽器首屏內容渲染完成的時間。對於用戶體驗來說,首屏時間是用戶對一個網站的重要體驗因素。通常一個網站,如果首屏時間在5秒以內是比較優秀的,10秒以內是可以接受的,10秒以上就不可容忍了。超過10秒的首屏時間用戶會選擇刷新頁面或立刻離開。

通常計算首屏的方法有

  • 首屏模塊標簽標記法

  • 統計首屏內載入最慢的圖片的時間

  • 自定義首屏內容計演算法

    1、首屏模塊標簽標記法

首屏模塊標簽標記法,通常適用於首屏內容不需要通過拉取數據才能生存以及頁面不考慮圖片等資源載入的情況。我們會在 HTML 文檔中對應首屏內容的標簽結束位置,使用內聯的 JavaScript 代碼記錄當前時間戳。如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>首屏</title>
  <script type="text/javascript">
    window.pageStartTime = Date.now();
  </script>
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
</head>
<body>
  <!-- 首屏可見模塊1 -->
  <div class="module-1"></div>
  <!-- 首屏可見模塊2 -->
  <div class="module-2"></div>
  <script type="text/javascript">
    window.firstScreen = Date.now();
  </script>
  <!-- 首屏不可見模塊3 -->
  <div class="module-3"></div>
    <!-- 首屏不可見模塊4 -->
  <div class="module-4"></div>
</body>
</html>

此時首屏時間等於 firstScreen - performance.timing.navigationStart;

事實上首屏模塊標簽標記法 在業務中的情況比較少,大多數頁面都需要通過介面拉取數據才能完整展示,因此我們會使用 JavaScript 腳本來判斷首屏頁面內容載入情況。

2、統計首屏內圖片完成載入的時間

通常我們首屏內容載入最慢的就是圖片資源,因此我們會把首屏內載入最慢的圖片的時間當做首屏的時間。

由於瀏覽器對每個頁面的 TCP 連接數有限制,使得並不是所有圖片都能立刻開始下載和顯示。因此我們在 DOM樹 構建完成後將會去遍歷首屏內的所有圖片標簽,並且監聽所有圖片標簽 onload 事件,最終遍歷圖片標簽的載入時間的最大值,並用這個最大值減去 navigationStart 即可獲得近似的首屏時間。

此時首屏時間等於 載入最慢的圖片的時間點 - performance.timing.navigationStart; //首屏時間嘗試: //1,獲取首屏基線高度 //2,計算出基線dom元素之上的所有圖片元素 //3,所有圖片onload之後為首屏顯示時間 //

function getOffsetTop(ele) {
    var offsetTop = ele.offsetTop;
    if (ele.offsetParent !== null) {
        offsetTop += getOffsetTop(ele.offsetParent);
    }
    return offsetTop;
}


var firstScreenHeight = win.screen.height;
var firstScreenImgs = [];
var isFindLastImg = false;
var allImgLoaded = false;
var t = setInterval(function() {
var i, img;
if (isFindLastImg) {
if (firstScreenImgs.length) {
for (i = 0; i < firstScreenImgs.length; i++) {
img = firstScreenImgs[i];
if (!img.complete) {
allImgLoaded = false;
break;
} else {
allImgLoaded = true;
}
}
} else {
allImgLoaded = true;
}
if (allImgLoaded) {
collect.add({
firstScreenLoaded: startTime - Date.now()
});
clearInterval(t);
}
} else {
var imgs = body.querySelector('img');
for (i = 0; i<imgs.length; i++) {
img = imgs[i];
var imgOffsetTop = getOffsetTop(img);
if (imgOffsetTop > firstScreenHeight) {
isFindLastImg = true;
break;
} else if (imgOffsetTop <= firstScreenHeight && !img.hasPushed) {
img.hasPushed = 1;
firstScreenImgs.push(img);
}
}
}
}, 0);
doc.addEventListener('DOMContentLoaded', function() {
var imgs = body.querySelector('img');
if (!imgs.length) {
isFindLastImg = true;
}
});




win.addEventListener('load', function() {
allImgLoaded = true;
isFindLastImg = true;
if (t) {
clearInterval(t);
}
collect.log(collect.global);
});

解釋一下思路,大概就是判斷首屏有沒有圖片,如果沒圖片就用domready時間,如果有圖,分2種情況,圖在首屏,圖不在首屏,如果在則收集,並判斷載入狀態,載入完畢之後則首屏完成載入,如果首屏沒圖,找到首屏下麵的圖,立刻觸發首屏完畢。可以想象這麼做前端收集是不准的,但是可以確保最晚不會超過win load,所以應該還算有些意義。。沒辦法,移動端很多瀏覽器不支持performance api,所以土辦法前端收集,想出這麼個黑魔法,在基線插入節點收集也是個辦法,但是不友好,而且現在手機屏幕這麼多。。

3、自定義模塊內容計演算法

由於統計首屏內圖片完成載入的時間比較複雜。因此我們在業務中通常會通過自定義模塊內容,來簡化計算首屏時間。如下麵的做法:

  • 忽略圖片等資源載入情況,只考慮頁面主要 DOM
  • 只考慮首屏的主要模塊,而不是嚴格意義首屏線以上的所有內容

實際上用performance.timing來計算首屏載入時間與白屏時間非常簡單與精確。不過目前只支持IE10和chrome 貼下其API的使用

                                                   var navigationStart = performance.timing.navigationStart;
//1488984540668
console.log(navigationStart);

//Wed Mar 08 2017 22:49:44 GMT+0800 (中國標準時間)
console.log(new Date(new Date(navigationStart)));
複製代碼
  redirectStart:到當前頁面的重定向開始的時間。但只有在重定向的頁面來自同一個域時這個屬性才會有值;否則,值為0
  redirectEnd:到當前頁面的重定向結束的時間。但只有在重定向的頁面來自同一個域時這個屬性才會有值;否則,值為0

console.log(performance.timing.redirectStart);//0
console.log(performance.timing.redirectEnd);//0
  fetchStart:開始通過HTTP GET取得頁面的時間

console.log(performance.timing.fetchStart);//1488984540668
  domainLookupStart:開始査詢當前頁面DNS的時間,如果使用了本地緩存或持久連接,則與fetchStart值相等
  domainLookupEnd:査詢當前頁面DNS結束的時間,如果使用了本地緩存或持久連接,則與fetchStart值相等

console.log(performance.timing.domainLookupStart);//1488984540670
console.log(performance.timing.domainLookupEnd);//1488984540671
  connectStart:瀏覽器嘗試連接伺服器的時間
  secureConnectionStart:瀏覽器嘗試以SSL方式連接伺服器的時間。不使用SSL方式連接時,這個屬性的值為0 
  connectEnd:瀏覽器成功連接到伺服器的時間

console.log(performance.timing.connectStart);//1488984540671
console.log(performance.timing.secureConnectionStart);//0
console.log(performance.timing.connectEnd);//1488984540719
  requestStart:瀏覽器開始請求頁面的時間
  responseStart:瀏覽器接收到頁面第一位元組的時間
  responseEnd:瀏覽器接收到頁面所有內容的時間

console.log(performance.timing.requestStart);//1488984540720
console.log(performance.timing.responseStart);//1488984540901
console.log(performance.timing.responseEnd);//1488984540902
  unloadEventStart:前一個頁面的unload事件開始的時間。但只有在前一個頁面與當前頁面來自同一個域時這個屬性才會有值;否則,值為0
  unloadEventEnd:前一個頁面的unload事件結束的時間。但只有在前一個頁面與當前頁面來自同一個域時這個屬性才會有值;否則,值為0

console.log(performance.timing.unloadEventStart);//1488984540902
console.log(performance.timing.unloadEventEnd);//1488984540903
  domLoading:document.readyState變為"loading"的時間,即開始解析DOM樹的時間
  domInteractive:document.readyState變為"interactive"的時間,即完成完成解析DOM樹的時間
  domContentLoadedEventStart:發生DOMContentloaded事件的時間,即開始載入網頁內資源的時間
  domContentLoadedEventEnd:DOMContentLoaded事件已經發生且執行完所有事件處理程式的時間,網頁內資源載入完成的時間
  domComplete:document.readyState變為"complete"的時間,即DOM樹解析完成、網頁內資源準備就緒的時間

console.log(performance.timing.domLoading);//1488984540905
console.log(performance.timing.domInteractive);//1488984540932
console.log(performance.timing.domContentLoadedEventStart);//1488984540932
console.log(performance.timing.domContentLoadedEventEnd);//1488984540932
console.log(performance.timing.domComplete);//1488984540932
  loadEventStart:發生load事件的時間,也就是load回調函數開始執行的時間 
  loadEventEnd:load事件已經發生且執行完所有事件處理程式的時間

console.log(performance.timing.loadEventStart);//1488984540933
console.log(performance.timing.loadEventEnd);//1488984540933
                                                       

第九問:你知道web Worker嗎?

多線程技術在服務端技術中已經發展的很成熟了,而在Web端的應用中卻一直是雞肋 在新的標準中,提供的新的WebWork API,讓前端的非同步工作變得異常簡單。 使用:創建一個Worker對象,指向一個js文件,然後通過Worker對象往js文件發送消息,js文件內部的處理邏輯,處理完畢後,再發送消息回到當前頁面,純非同步方式,不影響當前主頁面渲染。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script type="text/javascript">
        //創建線程 work對象
        var work = new Worker("work.js");      //work文件中不要存在跟ui代碼
        //發送消息
        work.postMessage("100");
        // 監聽消息
        work.onmessage = function(event) {
            alert(event.data);
        };
    </script>
</head>
<body>

</body>
</html>          

work.js

  onmessage = function (event) {
    //從1加到num
    var num = event.data;
    var result = 0;
    for (var i = 1; i <= num; i++) {
        result += i;
    }
    postMessage(result);
}
   

本文轉載於:

https://juejin.cn/post/6844904144864542733

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Android許可權詢問 AndroidMaifest.xml中聲明許可權 <!-- 聲明所有需要的許可權(包括普通許可權和危險許可權) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses- ...
  • vue組件中最常見的數據傳遞就是父子組件之間的傳遞,父組件可以通過 props 向下傳數據給子組件,子組件可以通過 $emit 事件攜帶數據給父組件。然而當兩個頁面沒有任關係,該如何通信?這就引出了 EventBus ( 事件匯流排 ) 這個概念 初始化 方法一:新建文件 首先需要初始化一個 Even ...
  • #背景 什麼是tapable、hook,平時做vue開發時的webpack 配置一直都沒弄懂,你也有這種情況嗎? 還是看源碼,閑來無聊又看一下webpack的源碼,看看能否找到一些寶藏 tapable和webpack沒有特定關係,可以先看下這篇文章,瞭解下這個小型庫 https://webpack. ...
  • JavaScript排序 — sort()方法 ——解決null、undefined、0之間的排序(混亂)問題 一、普通的數組排序 ​ JavaScript中用方法sort()為數組排序。sort()方法有一個可選參數,是用來確定元素順序的函數。如果這個參數被省略,那麼數組中的元素將按照ASCII字 ...
  • ##vue路由守衛用於登錄驗證許可權攔截 ###vue路由守衛 - 全局(router.beforeEach((to, from, next) =>來判斷登錄和路由跳轉狀態) ###主要方法: to:進入到哪個路由去 from:從哪個路由離開 next:路由的控制參數,常用的有next(true)和n ...
  • LRU 是 Least Recently Used 的縮寫,即最近最少使用。作為一種經典的緩存策略,它的基本思想是長期不被使用的數據,在未來被用到的幾率也不大,所以當新的數據進來時我們可以優先把這些數據替換掉。 一、基本要求 固定大小:限制記憶體使用。 快速訪問:緩存插入和查找操作應該很快,最好是 O ...
  • 一、前言 前段時間碰到了一個 Keybinding 相關的問題,於是探究了一番,首先大家可能會有兩個問題:Monaco Editor 是啥?Keybinding 又是啥? Monaco Editor: 微軟開源的一個代碼編輯器,為 VS Code 的編輯器提供支持,Monaco Editor 核心代 ...
  • 語法&關鍵字與保留字 本章篇幅較長故分成幾個小節來講 語法 區分大小寫 這個沒啥好講的,a和A是兩個變數。 標識符 標識符,就是變數、函數、屬性或函數參數的名稱。 標識符的組成規範,如下: 第一個字元必須是一個字母、下劃線( _ )或者美元符號( $ ); 剩下的其他字元可以使字母、下劃線、美元符號 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...