<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          14 個(gè)你必須知道的JavaScript 函數(shù)

          共 12622字,需瀏覽 26分鐘

           ·

          2022-07-26 18:16

          英文 | https://javascript.plainenglish.io/you-must-understand-these-14-javasript-functions-1f4fa1c620e2

          翻譯 | 楊小愛


          1、確定任意對象的具體類型

          眾所周知,JavaScript 中有六種原始數(shù)據(jù)類型(Boolean、Number、String、Null、Undefined、Symbol)和一個(gè)對象數(shù)據(jù)類型。 但是你知道對象數(shù)據(jù)類型可以細(xì)分為很多種子類型嗎? 一個(gè)對象可能是數(shù)組、函數(shù)、map等,如果我們要獲取對象的具體類型,應(yīng)該怎么做呢?

          代碼:

          function toRawType (value) {  let _toString = Object.prototype.toString;
          let str = _toString.call(value)
          return str.slice(8, -1)}

          解釋

          ECMAScript 有以下規(guī)則:

          對于不同的對象,調(diào)用 Object.prototype.toString() 時(shí)會返回不同的結(jié)果。

          而且,Object.prototype.toString() 的返回值總是‘[object’+‘tag’+‘]’的格式。 如果我們只想要中間的標(biāo)簽,我們可以通過正則表達(dá)式或者String.prototype.slice()刪除兩邊的字符。

          例子:

          toRawType(null) // "Null"toRawType(/sdfsd/) //"RegExp"

          2、緩存函數(shù)計(jì)算結(jié)果

          如果有這樣的功能:

          function computed(str) {    // Suppose the calculation in the funtion is very time consuming    console.log('2000s have passed')    return 'a result'}

          我們要緩存函數(shù)操作的結(jié)果, 稍后調(diào)用時(shí),如果參數(shù)相同,則不再執(zhí)行該函數(shù),而是直接返回緩存中的結(jié)果。 我們能做什么?

          代碼:

          function cached(fn){  // Create an object to store the results returned after each function execution.  const cache = Object.create(null);
          // Returns the wrapped function return function cachedFn (str) {
          // If the cache is not hit, the function will be executed if ( !cache[str] ) { let result = fn(str);
          // Store the result of the function execution in the cache cache[str] = result; }
          return cache[str] }}

          例子:

          3、實(shí)現(xiàn)Array.prototype.map

          這是 JavaScript 中一個(gè)有用的內(nèi)置方法,你應(yīng)該能夠自己實(shí)現(xiàn)此功能。

          代碼:

          const selfMap = function (fn, context) {    let arr = Array.prototype.slice.call(this)    let mappedArr = Array()    for (let i = 0; i < arr.length; i++) {        if (!arr.hasOwnProperty(i)) continue;        mappedArr[i] = fn.call(context, arr[i], i, this)    }    return mappedArr}
          Array.prototype.selfMap = selfMap;

          例子:

          4、實(shí)現(xiàn)Array.prototype.filter

          這是 JavaScript 中一個(gè)有用的內(nèi)置方法,你應(yīng)該能夠自己實(shí)現(xiàn)此功能。

          代碼:

          const selfFilter = function (fn, context) {    let arr = Array.prototype.slice.call(this)    let filteredArr = []    for (let i = 0; i < arr.length; i++) {        if(!arr.hasOwnProperty(i)) continue;         fn.call(context, arr[i], i, this) && filteredArr.push(arr[i])    }    return filteredArr}
          Array.prototype.selfFilter = selfFilter;

          例子:

          5、實(shí)現(xiàn) Array.prototype.some

          這是 JavaScript 中一個(gè)有用的內(nèi)置方法,你應(yīng)該能夠自己實(shí)現(xiàn)此功能。

          代碼:

          const selfSome = function (fn, context) {    let arr = Array.prototype.slice.call(this)    if(!arr.length) return false    for (let i = 0; i < arr.length; i++) {        if(!arr.hasOwnProperty(i)) continue;        let res = fn.call(context,arr[i],i,this)        if(res)return true    }    return false}
          Array.prototype.selfSome = selfSome;

          例子:

          6、實(shí)現(xiàn) Array.prototype.reduce

          這是 JavaScript 中一個(gè)有用的內(nèi)置方法,你應(yīng)該能夠自己實(shí)現(xiàn)此功能。

          代碼:

          const selfReduce = function (fn, initialValue) {    let arr = Array.prototype.slice.call(this)    let res    let startIndex    if (initialValue === undefined) {        for (let i = 0; i < arr.length; i++) {            if (!arr.hasOwnProperty(i)) continue            startIndex = i            res = arr[i]            break        }    } else {        res = initialValue    }
          for (let i = ++startIndex || 0; i < arr.length; i++) { if (!arr.hasOwnProperty(i)) continue res = fn.call(null, res, arr[i], i, this) } return res}
          Array.prototype.selfReduce = selfReduce;

          例子:

          7、實(shí)現(xiàn) Array.prototype.flat

          代碼:

          const selfFlat = function (depth = 1) {    let arr = Array.prototype.slice.call(this)    if (depth === 0) return arr    return arr.reduce((pre, cur) => {        if (Array.isArray(cur)) {            return [...pre, ...selfFlat.call(cur, depth - 1)]        } else {            return [...pre, cur]        }    }, [])}
          Array.prototype.selfFlat = selfFlat;

          例子:

          8、柯里化

          柯里化是一種將具有多個(gè)參數(shù)的函數(shù)評估為具有單個(gè)參數(shù)的函數(shù)序列的技術(shù)。

          換句話說,當(dāng)一個(gè)函數(shù)不是一次接受所有參數(shù)時(shí),而是接受第一個(gè)參數(shù)并返回一個(gè)新函數(shù),該函數(shù)接受第二個(gè)參數(shù)并返回一個(gè)新函數(shù),該函數(shù)接受第三個(gè)參數(shù),依此類推,直到所有參數(shù)都已履行。

          那就是我們將函數(shù)調(diào)用 add(1,2,3) 轉(zhuǎn)換為 add(1)(2)(3) 。 通過使用這種技術(shù),可以輕松地配置和重用小塊。

          為什么有用?

          • 柯里化可以幫助您避免一次又一次地傳遞相同的變量。

          • 它有助于創(chuàng)建高階函數(shù),它對事件處理非常有幫助。

          • 小部件可以輕松配置和重用。

          讓我們看一個(gè)簡單的添加函數(shù)。 它接受三個(gè)操作數(shù)作為參數(shù),并返回所有三個(gè)操作數(shù)的總和作為結(jié)果。

          function add(a,b,c){ return a + b + c;}

          你可以用太少(結(jié)果奇怪)或太多(多余的參數(shù)被忽略)來調(diào)用它。

          add(1,2,3) --> 6 add(1,2) --> NaNadd(1,2,3,4) --> 6 //Extra parameters will be ignored.

          如何將現(xiàn)有函數(shù)轉(zhuǎn)換為 curried 版本?

          代碼:

          function curry(fn) {    if (fn.length <= 1) return fn;    const generator = (...args) => {        if (fn.length === args.length) {
          return fn(...args) } else { return (...args2) => {
          return generator(...args, ...args2) } } } return generator}

          例子:

          9、去抖動

          去抖動只不過是減少不必要的耗時(shí)計(jì)算,以提高瀏覽器性能。在某些情況下,某些功能需要更多時(shí)間來執(zhí)行某個(gè)操作。例如,以電子商務(wù)網(wǎng)站上的搜索欄為例。

          假設(shè)用戶想要獲得“Tutorix 學(xué)習(xí)套件”。他在搜索欄中鍵入產(chǎn)品的每個(gè)字符。輸入每個(gè)字符后,從瀏覽器到服務(wù)器都會進(jìn)行一次 Api 調(diào)用,以獲取所需的產(chǎn)品。由于他想要“Tutorix 學(xué)習(xí)套件”,用戶必須從瀏覽器到服務(wù)器進(jìn)行 17 次 Api 調(diào)用。

          想象一個(gè)場景,當(dāng)數(shù)百萬人進(jìn)行相同的搜索從而調(diào)用數(shù)十億個(gè) Api 時(shí)。所以一次調(diào)用數(shù)十億個(gè) Api 肯定會導(dǎo)致瀏覽器性能變慢。為了減少這個(gè)缺點(diǎn),去抖動出現(xiàn)了。

          在這種情況下,去抖動將在兩次擊鍵之間設(shè)置一個(gè)時(shí)間間隔,假設(shè)為 2 秒。如果兩次擊鍵之間的時(shí)間超過 2 秒,則只會進(jìn)行 Api 調(diào)用。在這 2 秒內(nèi),用戶可以輸入至少一些字符,從而減少 Api 調(diào)用的這些字符。由于 Api 調(diào)用減少,瀏覽器性能將提高。必須注意,每次擊鍵都會更新 Debouncing 功能。

          代碼:

          const debounce = (func, time = 17, options = {    leading: true,    context: null}) => {    let timer;    const _debounce = function (...args) {        if (timer) {            clearTimeout(timer)        }        if (options.leading && !timer) {            timer = setTimeout(null, time)            func.apply(options.context, args)        }else{            timer = setTimeout(() => {                func.apply(options.context, args)                timer = null            }, time)        }    };
          _debounce.cancel = function () { clearTimeout(timer) timer = null }; return _debounce};

          10、 節(jié)流

          節(jié)流將以這樣一種方式更改函數(shù),即它可以在一個(gè)時(shí)間間隔內(nèi)最多觸發(fā)一次。 例如,無論用戶單擊按鈕多少次,限制將在 1000 毫秒內(nèi)僅執(zhí)行一次該功能。

          代碼:

          const throttle = (func, time = 17, options = {
          leading: true, trailing: false, context: null}) => { let previous = new Date(0).getTime() let timer; const _throttle = function (...args) { let now = new Date().getTime();
          if (!options.leading) { if (timer) return timer = setTimeout(() => { timer = null func.apply(options.context, args) }, time) } else if (now - previous > time) { func.apply(options.context, args) previous = now } else if (options.trailing) { clearTimeout(timer) timer = setTimeout(() => { func.apply(options.context, args) }, time) } };
          _throttle.cancel = () => { previous = 0; clearTimeout(timer); timer = null }; return _throttle};

          11、 延遲加載圖片

          延遲加載圖片意味著在網(wǎng)站上異步加載圖片——也就是說,在首屏內(nèi)容完全加載之后,甚至有條件地,只有當(dāng)它們出現(xiàn)在瀏覽器的視口中時(shí)。 

          這意味著如果用戶不一直向下滾動,則放置在頁面底部的圖像甚至不會被加載。

          代碼:

          // getBoundingClientRectlet imgList1 = [...document.querySelectorAll(".get_bounding_rect")]let num = imgList1.length
          let lazyLoad1 = (function () { let count = 0 return function () { let deleteIndexList = [] imgList1.forEach((img,index) => { let rect = img.getBoundingClientRect() if (rect.top < window.innerHeight) { img.src = img.dataset.src // Add picture to delete list after loading successfully deleteIndexList.push(index) count++ if (count === num) { //When all pictures are loaded, unbind scroll event document.removeEventListener('scroll',lazyLoad1) } } }) // Delete loaded pictures imgList1 = imgList1.filter((_,index)=>!deleteIndexList.includes(index))
          }})()

          12、數(shù)組隨機(jī)無序

          我們經(jīng)常需要打亂一個(gè)數(shù)組。

          代碼:

          // Randomly select one of all elements after the current element to exchange with the current elementfunction shuffle(arr) {    for (let i = 0; i < arr.length; i++) {        let randomIndex = i + Math.floor(Math.random() * (arr.length - i));        [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]]    }    return arr}
          // Generate a new array, randomly take an element from the original array and put it into the new arrayfunction shuffle2(arr) { let _arr = [] while (arr.length) { let randomIndex = Math.floor(Math.random() * (arr.length)) _arr.push(arr.splice(randomIndex, 1)[0]) } return _arr}

          例子:

          13、單例模式

          單例模式將特定對象的實(shí)例數(shù)限制為一個(gè),這個(gè)單一實(shí)例稱為單例模式。

          單例在需要從單個(gè)中心位置協(xié)調(diào)系統(tǒng)范圍的操作的情況下很有用。 一個(gè)例子是數(shù)據(jù)庫連接池。 池管理整個(gè)應(yīng)用程序的所有數(shù)據(jù)庫連接的創(chuàng)建、銷毀和生命周期,確保沒有連接“丟失”。

          單例減少了對全局變量的需求,這在 JavaScript 中尤為重要,因?yàn)樗拗屏嗣臻g污染和相關(guān)的名稱沖突風(fēng)險(xiǎn)。

          代碼:

          function proxy(func) {    let instance;    let handler = {        construct(target, args) {            if (!instance) {                // Create an instance if there is not exist                instance = Reflect.construct(func,args)            }            return instance        }    }    return new Proxy(func, handler)}

          // example
          function Person(name, age) { this.name = name this.age = age}
          const SingletonPerson = proxy(Person)
          let person1 = new SingletonPerson('zhl', 22)
          let person2 = new SingletonPerson('cyw', 22)
          console.log(person1 === person2) // true

          例子:

          14、實(shí)現(xiàn) JSON.stringify

          這是 JavaScript 中一個(gè)有用的內(nèi)置方法,你應(yīng)該能夠自己實(shí)現(xiàn)此功能。

          代碼:

          const isString = value => typeof value === 'string';const isSymbol = value => typeof value === 'symbol'const isUndefined = value => typeof value === 'undefined'const isDate = obj => Object.prototype.toString.call(obj) === '[object Date]'const isFunction = obj => Object.prototype.toString.call(obj) === '[object Function]';const isComplexDataType = value => (typeof value === 'object' || typeof value === 'function') && value !== null;const isValidBasicDataType = value => value !== undefined && !isSymbol(value); const isValidObj = obj => Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Object]';const isInfinity = value => value === Infinity || value === -Infinity

          // Symbol,undefined,function in array will become null// Infinity,NaN will also become nullconst processSpecialValueInArray = value => isSymbol(value) || isFunction(value) || isUndefined(value) || isInfinity(value) || isNaN(value) ? null : value;
          // Handling property values according to JSON specificationconst processValue = value => { if (isInfinity(value) || isNaN(value)) { return null } if (isString(value)) { return `"${value}"` } return value};

          // obj.loop = obj
          const jsonStringify = (function () { // Closure + WeakMap prevent circular references let wp = new WeakMap();
          //It is the function in the closure that recursively calls jsonstrify, not the jsonstrify function declared by const return function jsonStringify(obj) { if (wp.get(obj)) throw new TypeError('Converting circular structure to JSON'); let res = "";
          if (isComplexDataType(obj)) { if (obj.toJSON) return obj.toJSON; if (!isValidObj(obj)) { return } wp.set(obj, obj);
          if (Array.isArray(obj)) { res += "["; let temp = []; obj.forEach((value) => { temp.push( isComplexDataType(value) && !isFunction(value) ? jsonStringify(value) : `${processSpecialValueInArray(value, true)}` ) }); res += `${temp.join(',')}]` } else { res += "{"; let temp = []; Object.keys(obj).forEach((key) => {
          if (isComplexDataType(obj[key])) {
          if (isValidObj(obj[key])) { temp.push(`"${key}":${jsonStringify(obj[key])}`) } else if (isDate(obj[key])) { temp.push(`"${key}":"${obj[key].toISOString()}"`) } else if (!isFunction(obj[key])) { temp.push(`"${key}":{}`) } } else if (isValidBasicDataType(obj[key])) { temp.push(`"${key}":${processValue(obj[key])}`) } }); res += `${temp.join(',')}}` } } else if (isSymbol(obj)) { return } else { return obj } return res }})();

          // example
          let s = Symbol('s')let obj = { str: "123", arr: [1, {e: 1}, s, () => { }, undefined,Infinity,NaN], obj: {a: 1}, Infinity: -Infinity, nan: NaN, undef: undefined, symbol: s, date: new Date(), reg: /123/g, func: () => { }, dom: document.querySelector('body'),};
          console.log(jsonStringify(obj));console.log(JSON.stringify(obj));

          例子:

          總結(jié)

          以上就是我與你分享的14個(gè)JavaScript的函數(shù),這些函數(shù)也是我們作為一名web前端開發(fā)人員必須要知道的,希望對你有用,如果覺得對你有幫助的話,請記得點(diǎn)贊我,關(guān)注我,并將它分享給你身邊做開發(fā)的朋友,也許能夠幫助到他。



          學(xué)習(xí)更多技能

          請點(diǎn)擊下方公眾號

          瀏覽 44
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲AV人人澡人人爽人人乐 | 水蜜桃AV无码 | 综合热久久 | 蜜桃传媒一区二区 | 天天天日天天天天天天天日歌词 |