亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747


5 個(gè)提升你 JavaScript 編碼水平的實(shí)例

 

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

判斷數(shù)據(jù)類型

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

答案是:不可以,因?yàn)橛捎跉v史原因,在判斷原始類型時(shí),typeof null會(huì)等于object。而且對(duì)于對(duì)象來說,除了函數(shù),都會(huì)轉(zhuǎn)換成object。例子如下:

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

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

答案是:還是不可以,雖然instanceof是通過原型鏈來判斷的,但是對(duì)于對(duì)象來說,Array也會(huì)被轉(zhuǎn)換成Object,而且也不能區(qū)分基本類型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

所以該怎么辦呢?

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

所以為什么?

因?yàn)槊總€(gè)對(duì)象都有一個(gè)toString()方法,當(dāng)要將對(duì)象表示為文本值或以預(yù)期字符串的方式引用對(duì)象時(shí),會(huì)自動(dòng)調(diào)用該方法。默認(rèn)情況下,從Object派生的每個(gè)對(duì)象都會(huì)繼承toString()方法。如果此方法未在自定義對(duì)象中被覆蓋,則toString()返回[Object type],其中type是對(duì)象類型。所以就有以下例子:

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]

所以綜合上述知識(shí)點(diǎn),我們可以封裝出以下通用類型判斷方法:

var type = function(data) {      
  var toString = Object.prototype.toString;      
  var dataType = data instanceof Element                          
  ? 'element' // 為了統(tǒng)一DOM節(jié)點(diǎn)類型輸出                          
  : toString                              
  .call(data)                              
  .replace(/[objects(.+)]/, ''$1')                              
           .toLowerCase()      
  return dataType
}

使用方法如下:

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

通用的數(shù)組/類數(shù)組對(duì)象封裝

如果我們使用 ES5/ES6+的數(shù)組 API,很容易就能夠?qū)?shù)組進(jìn)行各類的循環(huán)操作,但是如果我們要循環(huán)一個(gè)類數(shù)組對(duì)象呢?

例如NodeList。直接循環(huán)是會(huì)報(bào)錯(cuò)的:

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

當(dāng)然我們可以用擴(kuò)展運(yùn)算符:

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

那如果我們不用擴(kuò)展運(yùn)算符呢?

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

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 元素節(jié)點(diǎn)的偏移量

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

我們先來看看例子:

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()這個(gè)方法。

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

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

使用方法如下:

var el = document.querySelector(".moveBox");
getOffset(el); // {top: xxx, left: xxx}
5 個(gè)提升你 JavaScript 編碼水平的實(shí)例

 

我們可以看上面的搖桿效果,這里就是利用了offset()去做位置判斷。具體實(shí)現(xiàn)代碼可以看: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()
}

上述是淡入淡出效果的具體實(shí)現(xiàn),這里是利用requestAnimationFrame對(duì)opacity通過遞歸的方式進(jìn)行修改。

其實(shí)這里需要提一個(gè)概念,就是時(shí)間分片

這是一個(gè)非常重要的概念,例如 React 的 Fiber 核心實(shí)現(xiàn)就是時(shí)間分片。它會(huì)將一個(gè)長(zhǎng)任務(wù)切分成一個(gè)含有若干小任務(wù)的任務(wù)隊(duì)列,然后一個(gè)接著一個(gè)的執(zhí)行。

requestAnimationFrame就是這樣一個(gè) API,它可以根據(jù)系統(tǒng)來決定回調(diào)函數(shù)的執(zhí)行時(shí)機(jī),其實(shí)也就是在下一次重繪之前更新動(dòng)畫幀,因?yàn)橛羞@樣的機(jī)制,所以能防止丟幀。

利用隊(duì)列的概念進(jìn)行數(shù)據(jù)操作

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

雖然很多人覺得了解數(shù)據(jù)結(jié)構(gòu)對(duì)前端作用不大,但是如果我們懂一些基礎(chǔ)的概念,是否在編碼時(shí)能夠更加擴(kuò)散我們的思維呢?我們看下面兩個(gè)例子:

獲取節(jié)點(diǎn)在該父節(jié)點(diǎn)下的坐標(biāo)。

如果我們要操作原生 DOM,那么是繞不開獲取節(jié)點(diǎn)在該父節(jié)點(diǎn)的下標(biāo)的這個(gè)功能的,那么我們?cè)撊绾螌?shí)現(xiàn)呢?

當(dāng)然就是利用我們的循環(huán)啦,對(duì)子元素集合進(jìn)行遍歷,直到確定下標(biāo)為止,代碼如下:

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

清空子節(jié)點(diǎn)

如果我們要清空某個(gè) DOM 節(jié)點(diǎn)的子節(jié)點(diǎn),我們有以下的方法:

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

上面只是提供一個(gè)思路,其實(shí)el.innerhtml = ''會(huì)更簡(jiǎn)潔。

利用 reduce 進(jìn)行數(shù)據(jù)優(yōu)化

數(shù)組去重

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

牛逼的 reduce

數(shù)據(jù)去重

首先我們來看看一個(gè)老生常談的問題,我們假設(shè)有這樣的一個(gè)對(duì)象:

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"  
  }];

現(xiàn)在我們要去重里面name重復(fù)的對(duì)象,這時(shí)候我們可以利用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);

批量生成對(duì)象元素

在魚頭的實(shí)際業(yè)務(wù)中,有一個(gè)操作是需要對(duì)類似以下的對(duì)象進(jìn)行操作的:

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

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

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);

文章來源:陳大魚頭

小節(jié)

今天的內(nèi)容就和大家分享到這里,感謝你的閱讀。如果你喜歡我的分享,麻煩給個(gè)關(guān)注、點(diǎn)贊加轉(zhuǎn)發(fā)哦,你的支持,就是我分享的動(dòng)力,后續(xù)會(huì)持續(xù)分享代碼片段,歡迎持續(xù)關(guān)注。

分享到:
標(biāo)簽:JavaScript
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定