バブルアルゴリズム
function bul(arr1) {
let temp = 0;
let arr = arr1;
let a = document.getElementById('a');
for (let i = 0; i < arr.length - 1; i++) {
//外循环,控制次数
for (let j = 0; j < arr.length - 1 -i; j++) {
//每次得到最大的数,循环次数就要减1
if (arr[j] > arr[j + 1]) {
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
a.innerHTML = arr;
}
重複排除 (複数のアイデア)
//1. es6
var unique = arr => [...new Set(arr)]
//2. es5
function unique(arr) {
var res = arr.filter(function(item, index, array) {
return array.indexOf(item) === index
})
return res
}
配列の平坦化 (複数のアイデア)
// 1. es6,循环递归
const flatten = (arr) => {
let res = [];
// item:当前元素 index:当前元素的下标 arrs:当前元素所属数组
arr.forEach((item, index, arrs) => {
if (Array.isArray(item)) {
res = res.concat(flatten(item))
} else {
// res.push(arrs[index])
res.push(item)
}
})
return res;
}
// 2. api
console.log(arr.flat(Infinity));
//3. 解构
const filter3 = (arr) => {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr
}
// 4. 看起来高级一点的reduce
const filter2 = (arr) => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? filter2(cur) : cur)
}, [])
}
手ぶれ補正スロットリング
中心となるアイデア: 単位時間あたりマクロ タスク キューに入るタイマーは 1 つだけです。
シナリオ: リクエストの送信、画面のスクロール、ウィンドウ サイズの縮小時に実行されるコード
。 手ぶれ補正:
function debound (fn,delay){
let timer = null;
return (...args)=>{
clearTimeout(timer)
timer = setTimeout(
()=>{
fn.apply(this,arg)
}
,delay)
}
}
スロットリング:
const throttle = (fn, delay = 500) => {
let flag = true;
return (...args) => {
if (!flag) return;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay);
};
};
手書きのバインド
アイデア: カスタム属性を使用して最初に独自の this を保存する
バインド関数の特徴
// 特徴 1. this のポイントを変更します 2. 元のオブジェクトの戻り値には影響しません 3. 複数のパラメーターを受け取ります 4. 返すものは関数です
Function.prototype.Mybind = (ctx,args)=>{
// 1. 将方法挂载到传入的ctx上去 2. 挂载之后调用 3. 将属性删除
return (...args2) => {
// 表示独一无二的值最大的用法是用来定义对象的唯一属性名。
// Symbol值不能与其他类型的值进行运算
// Symbol 值不可以和其他类型值进行混合运算,否则会报错
// Symbol 值如果想要作为属性名,那就不能再用点运算符,因为点运算符后面跟的总是字符串
// 在对象内部使用Symbol 值作为属性名的时候,必须要将值放在方括号中
let fn = Symbol(1);
ctx[fn] = this;
ctx[fn](...args.concat(args2));
delete ctx[fn];
}
}
深いコピー/浅いコピー
アイデア: 現在の項目が配列であるかオブジェクトであるかを判断するには、それは直接コピーではなく、直接コピーである場合は再帰的になります。
function copyObj(obj) {
let newObj = null
Array.isArray(obj) ? newObj = [] : newObj = {
}
for(let key in obj) {
if(type obj[key] === 'object') {
newObj[key] = copyObj(obj[key])
}else {
newObj[key] = copyObj(obj[key])
}
}
return newObj
}
手書きの約束すべて
アイデア: 渡された peomise 配列を周期的に呼び出します。1 つの Promise が失敗すると、Promise 全体が失敗します。
const PromiseAll = (iterator) =>{
// 使他变成数组
let promises = Array.from(iterator);
// 记录成功的promise
let index = 0;
// 记录成功的结果;
let res = [];
return new Promise((reslove,reject)=>{
// 1.遍历传进来的promise
for (let key in promises) {
promises[key]
.then((result) => {
res[key] = result;
if (++index === promises.length) {
reslove(res);
}
}).catch((err) => {
// 3.一旦有错误的就变为reject
reject(err);
});
}
})
}
約束を手書きではなく書いてみてください(個人的な学習能力をテストするだけです)
2 つの数値の合計
function addTwo(num,tar){
let map = new Map()
for(let i = 0; i<num.length;i++) {
if(map.has(tar-num[i])){
return [tar-num[i] , i]
}else {
map.set(num[i],i)
}
}
return []
}
手書きの反転配列
アイデア: ダブルポインタで先頭と末尾を入れ替えます。中間値に注意してください。そうでないと、再び反転します。
function reverse(arr) {
let mid = Math.floor(arr.length / 2)
let end = arr.length - 1
for (let i = 0; i < mid ; i++) {
let temp = arr[i]
arr[i] = arr[end]
arr[end] = temp
end--
}
return arr
}
// ps:大佬的代码。我也看不懂
// 算法类型
// var reverse = function(x) {
// let res = 0;
// while(x){
// res = res * 10 + x % 10;
// if(res > Math.pow(2, 31) - 1 || res < Math.pow(-2, 31)) return 0;
// x = ~~(x / 10);
// }
// return res;
// };
新しいキーワードの実装プロセス
アイデア:
new は新しいオブジェクトを生成します。
新しいオブジェクトはコンストラクターのプロパティにアクセスできる必要があるため、そのプロトタイプを再指定する必要があります。コンストラク
ターは明示的に返すことができます。
let obj= new Object()
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
// ret || obj 这里这么写考虑了构造函数显示返回 null 的情况
return typeof ret === 'object' ? ret || obj : obj;