亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

5個提升你JavaScript編碼水平的實例是怎樣的

發布時間:2021-09-30 17:28:50 來源:億速云 閱讀:152 作者:柒染 欄目:web開發

這篇文章給大家介紹5個提升你JavaScript編碼水平的實例是怎樣的,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

雖然 2020 的今天,各種前端框架、工具林立,而這些框架跟工具也幫我們提前解決了不少麻煩的問題,但是工具始終是工具,扎實的基本功才是最核心的,現在一起來通過幾個實際的代碼片段來提高我們原生 JS 的編碼水平。

判斷數據類型

首先來提問一個:typeof是否能正確判斷類型?

答案是:不可以,因為由于歷史原因,在判斷原始類型時,typeof null會等于object。而且對于對象來說,除了函數,都會轉換成object。例子如下:

typeof 1; // 'number'
typeof "1"; // 'string'
typeof null; //
typeof []; // 'object'
typeof {}; // 'object'
typeof window.alert; // 'function'

再來提問一個,instanceof是否能正確判斷類型?

答案是:還是不可以,雖然instanceof是通過原型鏈來判斷的,但是對于對象來說,Array也會被轉換成Object,而且也不能區分基本類型string和boolean。例如:

function Func() {}
const func = new Func();
console.log(func instanceof Func); // true
const obj = {};
const arr = [];
obj instanceof Object; // true
arr instanceof Object; // true
arr instanceof Array; // true
const str = "abc";
const str2 = new String("abc");
str instanceof String; // false
str2 instanceof String; // true

所以該怎么辦呢?

這時候我們可以使用:Object.prototype.toString.call()

所以為什么?

因為每個對象都有一個toString()方法,當要將對象表示為文本值或以預期字符串的方式引用對象時,會自動調用該方法。默認情況下,從Object派生的每個對象都會繼承toString()方法。如果此方法未在自定義對象中被覆蓋,則toString()返回[Object type],其中type是對象類型。所以就有以下例子:

Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call("1"); // [object String]
Object.prototype.toString.call(1); // [object Numer]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]

所以綜合上述知識點,我們可以封裝出以下通用類型判斷方法:

var type = function(data) {      
 var toString = Object.prototype.toString;      
 var dataType = data instanceof Element                          
 ? 'element' // 為了統一DOM節點類型輸出                          
 : toString                              
 .call(data)                              
 .replace(/\[object\s(.+)\]/, ''$1')                              
          .toLowerCase()      
 return dataType
}

使用方法如下:

type("a"); // string
type(1); // number
type(window); // window
type(document.querySelector("h2")); // element

通用的數組/類數組對象封裝

如果我們使用 ES5/ES6+的數組 API,很容易就能夠對數組進行各類的循環操作,但是如果我們要循環一個類數組對象呢?

例如NodeList。直接循環是會報錯的:

document.querySelectorAll("div").map(e => e); // Uncaught TypeError: document.querySelectorAll(...).map is not a function

當然我們可以用擴展運算符:

[...document.querySelectorAll("div")].map(e => e);

那如果我們不用擴展運算符呢?

那么我們就可以利用call的特性,將NodeList里的元素一個一個的插入到數組中,例子如下:

var listMap = function(array, type, fn) {  
 return !fn ? array : Array.prototype[type]["call"](array, fn);};

使用方法如下:

var divs = document.querySelectorAll("div");
listMap(divs, "forEach", function(e) {  
 console.log(e);
});

獲取 dom 元素節點的偏移量

如果有用過jQuery的童鞋,就一定不會忘記$('').offset()這個 api 的強大功能,這個 api 可以輕易獲取元素的偏移量,那么如果我們不用jQuery該怎么實現呢?

我們先來看看例子:

var getOffset = function(el) { 

 var scrollTop =
     el.getBoundingClientRect().top +    
     document.body.scrollTop +    
     document.documentElement.scrollTop;  
 var scrollLeft =    
     el.getBoundingClientRect().left +    
     document.body.scrollLeft +    
     document.documentElement.scrollLeft;  
 return {    
   top: scrollTop,    
   left: scrollLeft  
 };
};

首先我們先來看getBoundingClientRect()這個方法。

getBoundingClientRect()方法返回元素的大小及其相對于視口的位置。返回值是一個 DOMRect 對象,是與該元素相關的 CSS 邊框集合 。

然后就是document.body.scrollTop 跟 document.documentElement.scrollTop這兩個是一個功能,只不過在不同的瀏覽器下會有一個始終為 0,所以做了以上的兼容性處理。所以當我們做拖拽功能的時候,就可以依賴上以上屬性。

使用方法如下:

var el = document.querySelector(".moveBox");
getOffset(el); // {top: xxx, left: xxx}

5個提升你JavaScript編碼水平的實例是怎樣的

我們可以看上面的搖桿效果,這里就是利用了offset()去做位置判斷。具體實現代碼可以看:https://codepen.io/krischan77/pen/zYxPNPy

Fade 特效

// Fade in
var fadeIn = function (el) {    
 el.style.opacity = 0    
 var last = +new Date()    
 var tick = function() {        
   el.style.opacity = +el.style.opacity + (new Date() - last) / 400        
   last = +new Date()        
   if (+el.style.opacity < 1) {            
     requestAnimationFrame(tick))        
   }    
 }    
 tick()
}
// Fade out
var fadeOut = function (el) {  
 el.style.opacity = 1    
 var last = +new Date()    
 var tick = function() {        
   el.style.opacity = +el.style.opacity - (new Date() - last) / 400        
   last = +new Date()        
   if (+el.style.opacity > 0) {            
     requestAnimationFrame(tick)        
   }    
 }    
 tick()
}

上述是淡入淡出效果的具體實現,這里是利用requestAnimationFrame對opacity通過遞歸的方式進行修改。

其實這里需要提一個概念,就是時間分片。

這是一個非常重要的概念,例如 React 的 Fiber 核心實現就是時間分片。它會將一個長任務切分成一個含有若干小任務的任務隊列,然后一個接著一個的執行。

requestAnimationFrame就是這樣一個 API,它可以根據系統來決定回調函數的執行時機,其實也就是在下一次重繪之前更新動畫幀,因為有這樣的機制,所以能防止丟幀。

利用隊列的概念進行數據操作

隊列(queue),是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中通常用鏈表或者數組來實現。隊列只允許在后端(稱為 rear)進行插入操作,在前端(稱為 front)進行刪除操作。

雖然很多人覺得了解數據結構對前端作用不大,但是如果我們懂一些基礎的概念,是否在編碼時能夠更加擴散我們的思維呢?我們看下面兩個例子:

獲取節點在該父節點下的坐標。

如果我們要操作原生 DOM,那么是繞不開獲取節點在該父節點的下標的這個功能的,那么我們該如何實現呢?

當然就是利用我們的循環啦,對子元素集合進行遍歷,直到確定下標為止,代碼如下:

var index = function(el) {  
 if (!el) {    
   return -1;  
 }  
 var i = 0;  
 while ((el = el.previousElementSibling)) {    
   i++;  
 }  
 return i;
};

清空子節點

如果我們要清空某個 DOM 節點的子節點,我們有以下的方法:

var empty = function(el) {  
 while (el.firstChild) {    
   el.removeChild(el.firstChild);  
 }
};

上面只是提供一個思路,其實el.innerHTML = ''會更簡潔。

利用 reduce 進行數據優化

數組去重

沒錯,又是一個老生常談的問題,數組去重,但是我們這次去除的不僅僅是單個的數據,而是擁有某個相同鍵值的對象集合。例如下面的例子,我們有以下的數據:

牛逼的 reduce

數據去重

首先我們來看看一個老生常談的問題,我們假設有這樣的一個對象:

const data = [  
 {    
   name: "Kris",    age: "24"  
 },  
 {    
   name: "Andy",    age: "25"  
 },  
 {    
   name: "Kitty",    age: "25"  
 },  
 {    
   name: "Andy",    age: "25"  
 },  
 {    
   name: "Kitty",    age: "25"  
 },  
 {    
   name: "Andy",    age: "25"  
 },  
 {    
   name: "Kitty",    age: "25"  
 }];

現在我們要去重里面name重復的對象,這時候我們可以利用reduce,例子如下:

const dataReducer = (prev, cur, idx) => {  
 let obj = {};  
 const { name } = cur;  
 obj[name] = cur;  
 return {    
   ...prev,    
   ...obj  
 };
};
const reducedData = data.reduce(dataReducer, {});
let newData = Object.values(reducedData);

批量生成對象元素

在魚頭的實際業務中,有一個操作是需要對類似以下的對象進行操作的:

{    
 a1: 'data',    
 a2: 'data',  
 ...,    
 an: 'data'
}

像我這么懶的魚,肯定不會一個個手寫,所以就有了以下方法

const createList = (item, idx) => {  
 let obj = {};  
 obj[`a${idx}`] = "data";  
 return obj;
};
const listReducer = (acc, cur) => (!acc ? { ...cur } : { ...cur, ...acc });
const obj = Array.from(new Array(20), createList).reduce(listReducer);

關于5個提升你JavaScript編碼水平的實例是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

舒城县| 曲松县| 新源县| 蓝山县| 平原县| 泾源县| 白银市| 健康| 天津市| 漾濞| 滨海县| 玉门市| 永修县| 渝中区| 微山县| 修文县| 武清区| 晋中市| 双峰县| 板桥市| 湾仔区| 松原市| 太原市| 高邮市| 肇源县| 广灵县| 滦平县| 科技| 措勤县| 武陟县| 溧水县| 林西县| 景泰县| 临沭县| 西乌珠穆沁旗| 黎城县| 礼泉县| 五大连池市| 阜城县| 武胜县| 皋兰县|