フロントエンド エンジニアがいくつかの一般的なコードを js で手書きしました。ある程度の根拠がある、そうでないと理解できない

バブルアルゴリズム

 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;

おすすめ

転載: blog.csdn.net/work33/article/details/127143528