目次
マップ紹介
文法
array.map(callback[, thisArg])
パラメータ
折り返し電話
元の配列内の要素は、このメソッドを通過した後に新しい要素を返します。
現在の価値
コールバックの最初のパラメータは、配列内で現在渡されている要素です。
索引
callback の 2 番目のパラメータは、配列内で現在渡されている要素のインデックスです。
配列
callback の 3 番目のパラメータ、map メソッドを呼び出す配列。
この引数
コールバック関数の実行時に this が指すオブジェクト。
戻り値
コールバック関数の戻り値で構成される新しい配列。
例
https://www.codewars.com/kata/double-char
文字列を指定すると、各文字 (大文字と小文字が区別される) が 1 回繰り返される文字列を返す必要があります。
doubleChar("String") ==> "SSttrriinngg"
doubleChar("Hello World") ==> "HHeelllloo WWoorrlldd"
doubleChar("1234!_ ") ==> "11223344!!__ "
幸運を!
答え:
const doubleChar = (str) =>
str
.split('')
.map((i) => i.repeat(2))
.join('');
リデュースの概要
文法
arr.reduce(callback, [initialValue]);
パラメータ
折り返し電話
配列内の各値に対して実行する関数。次の 4 つのパラメーターを使用します。
アキュムレータ
コールバックへの最後の呼び出しによって返された値、または提供された初期値 (initialValue)
現在の価値
処理される配列内の要素
現在のインデックス
データ内で処理されている要素のインデックス。initialValues が指定されていない場合は、デフォルトで 0 から始まります。
配列
reduce を呼び出す配列
初期値
コールバックの最初の呼び出しの最初の引数として。
戻り値
この関数は処理結果を蓄積します。
例
https://www.codewars.com/kata/beginner-reduce-but-grow
整数の配列 (x) を指定すると、値を順番に乗算した結果を返します。例:
[1, 2, 3] --> 6
初心者の場合は、reduce メソッドを使用してみてください。これは非常に便利なので、知っておくと良いでしょう。
配列は空にはなりません。
答え:
const grow = (x) => x.reduce((r, i) => r * i, 1);
定期交換
参考:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp
道具:
- RegExp テスター (Chrome プラグイン)
例
10 個の整数 (0 ~ 9) の配列を受け取り、それらの数値の文字列を電話番号の形式で返す関数を作成します。
例:
createPhoneNumber([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) // => returns "(123) 456-7890"
このチャレンジを完了するには、返される形式が正しい必要があります。
閉じ括弧の後のスペースを忘れないでください。
トピックのアドレス: https://www.codewars.com/kata/create-phone-number
答え:
const createPhoneNumber = (n) => n.join('').replace(/(\d{3})(\d{3})(\d{3})/, '($1) $2-$3');
例外キャプチャ
ES5 の従来のアプローチ
コード ブロックの実行でエラー失敗がスローされたと仮定すると、エラーを捕捉する方法は次のとおりです。
try {
// 代码块执行,并抛出 fail 错误
throw new Error('fail');
} catch (e) {
console.log(e);
}
タイマー
まず上記のコードを書き直してタイマーを追加しましょう。
try {
setTimeout(() => {
throw new Error('fail');
// Uncaught Error: fail
}, 1000);
} catch (e) {
console.log(e);
}
このように、タイマーの外で try/catch をスローしても内部エラーをキャッチできません。
正しいアプローチは次のとおりです。
setTimeout(() => {
try {
throw new Error('fail');
} catch (e) {
console.log(e);
}
}, 1000);
約束
function doSomething() {
return new Promise((resolve, reject) => {
// 同步代码中的 throw 可以被捕捉到
throw new Error('fail');
});
}
doSomething()
.then((x) => {
console.log('success:', x);
})
.catch((err) => {
console.log('fail:', err);
});
このように書いても問題はありませんが、エラーは検出される可能性があります。ただし、少し変更する限り、問題が発生する可能性があります。例えば:
function doSomething() {
return new Promise((resolve, reject) => {
// 异步代码中的 throw 不能被 Promise 的 catch 捕捉到
setTimeout(() => {
throw new Error('fail');
}, 1000);
});
}
doSomething()
.then((x) => {
console.log('success:', x);
})
.catch((err) => {
console.log('fail:', err);
});
ここでスローされますが、エラーは捕捉されません。したがって、Promise では通常、reject を通じてエラーをスローします。
function doSomething(x) {
return new Promise((resolve, reject) => reject(x));
}
doSomething('fail')
.then((x) => {
console.log('success:', x);
})
.catch((err) => {
console.log('fail:', err);
});
// fail: fail
さらに、もう 1 つの興味深い詳細があり、catch の後に .then を追加すると実行が継続されます。
function doSomething(x) {
return new Promise((resolve, reject) => reject(x));
}
doSomething('fail')
.then((x) => {
console.log('success:', x);
})
.catch((err) => {
console.log('fail:', err);
// 这里可以写 return 给下面的方法继续执行
})
.then((x) => {
console.log('continue:', x);
});
// fail: fail
// continue: undefined
非同期/待機
基本的に、Async/Await は Promise を通じて実装されるため、上記の Promise の説明と基本的に同じです。
次のように、await メソッドの外側で try/catch をネストできます。
function doSomething(x) {
return new Promise((resolve, reject) => reject(x));
}
(async () => {
try {
const result = await doSomething('fail');
console.log('success:', result);
// return 返回
} catch (err) {
console.log('fail:', err);
// return 返回
}
})();
// fail: fail
しかし、ここで問題が発生し、例えば関数がリターンする必要がある場合、return 文を 2 回記述する必要があり、これは正常ですが、正常な場合は結果を返し、異常な場合はどちらかを返しますthrow new Error()
。ちょっとしたコツがあって、次のように書くことができます。
function doSomething(x) {
return new Promise((resolve, reject) => reject(x));
}
(async () => {
const result = await doSomething('fail').catch((err) => {
console.log('fail:', err);
return 0; // 默认值
});
console.log('success:', result);
})();
// fail: fail
// success: 0
エラーが検出されたら、デフォルト値を再割り当てし、コードの実行を続行します。
イベントの代表団
たとえば、イベント バインディングは、AJAX リクエストによって返された結果のボタンに対して実行されますclick
。
var handleClick = function (e) {
if (e.target && e.target.nodeName.toLowerCase() === 'button') {
// Codes Here
}
};
parentNode.addEventListener('click', handleClick);
ディープクローン
問題現象:
var obj1 = {
key1: 'value1',
key2: 'value2',
children: {
key3: 'value3',
key4: 'value4'
}
};
var obj2 = Object.assign({
}, obj1);
obj2.children.key3 = 'test';
console.log(obj1.children);
// { key3: 'test', key4: 'value4' }
簡単な解決策:
const obj2 = JSON.parse(JSON.stringify(obj1));
スクロールデバウンス
フロントエンドのスクロールリスニングイベントのトリガー頻度が高すぎる問題を解決するために使用されます。
コアコード:
function debounce(func, wait = 20, immediate = true) {
var timeout;
return function () {
var context = this,
args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
サンプルコード:
function testFunc(e) {
console.count(e);
}
window.addEventListener('scroll', () => console.count('bounce'));
window.addEventListener('scroll', debounce(testFunc));
ブラウザでテストします。
Map または For を使用したトラバース
同じ横断ですが、実際には大きく異なります。
比較した
地図
自分を変えてください。
[1, 2, 3, 4, 5].map((x) => x + 1);
// [ 2, 3, 4, 5, 6 ]
ために
ただループするだけです。
ベンチマークテスト
ベンチマークスクリプト:
suite('iterator', function () {
bench('for', function () {
const a = [1, 2, 3, 4, 5];
for (let i = 0; i < a.length; i++) {
// nothing
}
});
bench('foreach', function () {
const a = [1, 2, 3, 4, 5];
a.forEach(function (d) {
// nothing
});
});
bench('for of', function () {
const a = [1, 2, 3, 4, 5];
for (let i of a) {
// nothing
}
});
bench('map', function () {
const a = [1, 2, 3, 4, 5];
a.map((x) => x);
});
});
試験結果:
iterator
50,038,931 op/s » for
8,980,276 op/s » foreach
8,990,758 op/s » for of
1,713,807 op/s » map
Suites: 1
Benches: 4
Elapsed: 5,710.33 ms
結論は
ループのみがfor
最も信頼性が高くなります。
foreach
とほぼ同じですfor ... of
。
map
最低のパフォーマンス。
変更イベントに反応して値を割り当てるトリガー
var setValue = function (element, value) {
element.value = value;
if ('createEvent' in document) {
var event = new Event('input', {
bubbles: true });
element.dispatchEvent(event);
} else {
element.fireEvent('onchange');
}
};
パイプラインオペレーター(案)
現在ドラフト段階: https://github.com/tc39/proposal-pipeline-operator
function doubleSay(str) {
return `${
str}, ${
str}`;
}
function capitalize(str) {
return str[0].toUpperCase() + str.substring(1);
}
function exclaim(str) {
return `${
str}!`;
}
let result = 'hello' |> doubleSay |> capitalize |> exclaim;
result |> console.log;
//=> "Hello, hello!"
プロジェクトテンプレート: https://github.com/willin/esnext-pipeline-biolerplate
非同期 (ES 7)
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
複数のコマンドawait
に続く非同期操作の場合、後続関係がない場合は、それらを同時にトリガーさせるのが最善です。
let foo = await getFoo();
let bar = await getBar();
上記のコードでは、getFoo
と はgetBar
2 つの独立した非同期操作 (つまり、互いに独立) であり、二次関係として記述されています。getFoo
これは完了後にのみ実行され、getBar
同時にトリガーされる可能性があるため、時間がかかります。
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
上記 2 つの書き込み方法、 、getFoo
をgetBar
同時に実行することで、プログラムの実行時間を短縮できます。
プロキシ (ES6)
Node v6.1.0 以降のバージョンはテストされ、統合されています。
サンプルコード:
const proxy = new Proxy(
{
},
{
get: (target, property) => [target, property]
}
);
console.log(proxy.func); // [ {}, 'func' ]
console.log(proxy.func('123')); // TypeError: proxy.func is not a function
const proxy = new Proxy(
{
},
{
get: (target, property) => (test) => [target, property, test]
}
);
console.log(proxy.func); // [Function]
console.log(proxy.func('123')); // [ {}, 'func', '123' ]
ES6 の範囲
For ループを例に挙げます。
var funcs = [];
for (var i = 0; i < 10; i += 1) {
funcs.push(function () {
console.log(i);
});
}
funcs.forEach((func) => func());
// 输出 10 十次
閉鎖:
var funcs = [];
for (var i = 0; i < 10; i += 1) {
funcs.push((function(value){
console.log(value); }(i));
}
funcs.forEach(func => func());
// 0 到 9 依次输出
ES6 では次のように簡略化できます。
const funcs = [];
for (let i = 0; i < 10; i += 1) {
funcs.push(() => console.log(i));
}
funcs.forEach((func) => func());
// 0 到 9 依次输出
関数が関数を作成する
var add = new Function('first', 'second = first', 'return first + second');
console.log(add(1, 1)); // 2
console.log(add(1)); // 2
var pickFirst = new Function('..args', 'return args[0]');
console.log(pickFirst(1, 2)); // 1
ES6で値を交換する
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
API AJAX を取得する
ブラウザの互換性
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-3HRKmB2K-1690025164220)(/basic/js/fetch.png)]
サポートチェック
if (typeof fetch === 'function' && typeof window.fetch === 'function') {
// 支持
}
if (typeof fetch !== 'function' || typeof window.fetch !== 'function') {
// 不支持
}
サンプルコード
var req = new Request('/data.json', {
method: 'POST', cache: 'reload' });
fetch(req)
.then(function (res) {
return res.json();
})
.then(function (data) {
console.log(data);
});
クロスドメインCookieの設定
credentials
資格情報パラメータ
fetch('a.com/api', {
credentials: 'include' }).then(function (res) {
// ...
});
また
var req = new Request('/data.json', {
method: 'POST', cache: 'reload', credentials: 'include' });
fetch(req)
.then(function (res) {
return res.json();
})
.then(function (data) {
console.log(data);
});