ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptの5つの一般的な関数を詳しく解説
JavaScript ではよく議論される問題がいくつかあります。これらの問題については、人によってさまざまな考えがあります。これ以上苦労することなく、自分で実装するのが最善の方法です。
配列を平坦化する方法はたくさんありますが、最終的に最善の方法は、基本的なルーチンを理解できるように、指定された深さで平坦化メソッドを再帰して実装することです。
function flattenDepth(array, depth = 1) { let result = [] array.forEach(item => { let d = depth if (Array.isArray(item) && d > 0) { result.push(...(flattenDepth(item, --d))) } else { result.push(item) } }) return result } console.log(flattenDepth([1, [2, [3, [4]], 5]])) // [ 1, 2, [ 3, [ 4 ] ], 5 ] console.log(flattenDepth([1, [2, [3, [4]], 5]], 2)) // [ 1, 2, 3, [ 4 ], 5 ] console.log(flattenDepth([1, [2, [3, [4]], 5]], 3)) // [ 1, 2, 3, 4, 5 ]
再帰的な実装は非常にシンプルで理解しやすいです。つまり、各項目を走査し、項目が配列の場合、その項目を引き続き呼び出すようにします。このパラメータは配列にとって非常に重要なので、各項目には役割があるため、ループ内に配置されます。
関数のカリー化については、人それぞれの理解と実装方法があります。一言で説明すると、十分なパラメーターがなければ関数は実行されます。十分になるまで前のパラメータが保存されます。
function curry(func) { var l = func.length return function curried() { var args = [].slice.call(arguments) if(args.length < l) { return function() { var argsInner = [].slice.call(arguments) return curried.apply(this, args.concat(argsInner)) } } else { return func.apply(this, args) } } } var f = function(a, b, c) { return console.log([a, b, c]) }; var curried = curry(f) curried(1)(2)(3) // => [1, 2, 3] curried(1, 2)(3) // => [1, 2, 3] curried(1, 2, 3) // => [1, 2, 3]
上記のコードを見ると難しくありませんが、パラメータの数を判断するたびに、カリー化された関数のパラメータの数と比較され、その数より小さい場合は返し続けます。それ以外の場合は関数が実行されます。
私の理解によれば、手ぶれ補正とは、何度トリガーしても、最後のトリガーから指定した時間が経過するまではトリガーされないことを意味します。この説明に続いて、基本バージョンを作成します。
function debounce(func, wait) { var timer return function() { var context = this var args = arguments clearTimeout(timer) timer = setTimeout(function() { func.apply(context, args) }, wait) } }
ここで、最初と最後にトリガーされるという要件があり、スペースバーを押すたびに関数のテストを容易にするためにテストページを作成します。手ぶれ補正機能とスロットル機能をテストする場合、数値は 1 ずつ増加します。
<!DOCTYPE html> <html lang="zh-cmn-Hans"> <head> <style> #container{text-align: center; color: #333; font-size: 30px;} </style> </head> <body> <p id="container"></p> <script> var count = 1 var container = document.getElementById('container') function getUserAction(e) { // 空格 if (e.keyCode === 32) { container.innerHTML = count++ } } // document.onkeydown = debounce(getUserAction, 1000, false, true) document.onkeydown = throttle(getUserAction, 1000, true, true) function debounce(func, wait, leading, trailing) {} function throttle(func, wait, leading, trailing) {} </script> </body> </html>
先頭と末尾の 2 つのパラメータは、先頭と末尾を実行するかどうかを決定するために使用されます。先頭が true の場合、スペースを押すたびに 1 回実行されます。末尾が true の場合、最後のトリガーが実行されます。終了するたびに実行されます。手ぶれ補正機能の距離、両方が true の場合、最初にスペースを押すと 1 が追加され、すぐにスペースを押すと、この時点では内部の getUserAction は実行されませんが、末尾を false に放した後に実行されます。 、手放した後は実行されません。
function debounce(func, wait, leading, trailing) { var timer, lastCall = 0, flag = true return function() { var context = this var args = arguments var now = + new Date() if (now - lastCall < wait) { flag = false lastCall = now } else { flag = true } if (leading && flag) { lastCall = now return func.apply(context, args) } if (trailing) { clearTimeout(timer) timer = setTimeout(function() { flag = true func.apply(context, args) }, wait) } } }
説明します、最後の呼び出しの時間が記録されるたびに、それが間隔より小さい場合、最初の実行以降は実行されません。間隔を指定するか、間隔の後に呼び出された場合は、フラグをリセットして、上記の基本バージョンと比較します。
スロットルとは、どのようにトリガーされたとしても、指定された間隔に従って実行されることを意味します。 基本バージョンもあります。
function throttle(func, wait) { var timer return function() { var context = this var args = arguments if (!timer) { timer = setTimeout(function () { timer = null func.apply(context, args) }, wait) } } }
は、手ぶれ補正機能のような 2 つのパラメーターも追加します。実際、この 2 つのコードは非常に似ています。
function throttle(func, wait, leading, trailing) { var timer, lastCall = 0, flag = true return function() { var context = this var args = arguments var now = + new Date() flag = now - lastCall > wait if (leading && flag) { lastCall = now return func.apply(context, args) } if (!timer && trailing && !(flag && leading)) { timer = setTimeout(function () { timer = null lastCall = + new Date() func.apply(context, args) }, wait) } else { lastCall = now } } }
オブジェクトコピーが深いコピーと浅いコピーに分けられることは誰もが知っています
JSON.parse(JSON.stringify(obj))
もう一つの方法は再帰
function clone(value, isDeep) { if (value === null) return null if (typeof value !== 'object') return value if (Array.isArray(value)) { if (isDeep) { return value.map(item => clone(item, true)) } return [].concat(value) } else { if (isDeep) { var obj = {} Object.keys(value).forEach(item => { obj[item] = clone(value[item], true) }) return obj } return { ...value } } } var objects = { c: { 'a': 1, e: [1, {f: 2}] }, d: { 'b': 2 } } var shallow = clone(objects, true) console.log(shallow.c.e[1]) // { f: 2 } console.log(shallow.c === objects.c) // false console.log(shallow.d === objects.d) // false console.log(shallow === objects) // false
を使用することです。基本型を直接返します。参照型の場合は、clone メソッドを再帰的に走査して呼び出します。
実際、上記のメソッドの一般的な考え方は、クロージャの使用を含む再帰関数と高階関数の使用です。フロントエンドはこれらの質問を自分で実装するのが最善です。を理解するのに役立ちます。
関連する推奨事項:
JavaScriptでのさまざまな一般的な関数定義方法_javascriptスキル
以上がJavaScriptの5つの一般的な関数を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。