Skip to content

浅拷贝

js
function ShallowCopy(arr) {
	let newArr = [];
	arr.forEach((element, index) => {
		newArr[index] = element;
	});
	return newArr;
}

深拷贝

js
function DeepCopy(obj) {
	let res = obj instanceof Array ? [] : {};
	for (const key in obj) {
		if (obj.hasOwnProperty(key)) {
			const element = obj[key];
			res[key] = element instanceof Object ? DeepCopy(element) : element;
		}
	}
	return res;
}

节流

js
function throttle(fn, delay, ...param) {
	let timer;
	return function () {
		let args = arguments,
			context = this;
		if (!timer) {
			timer = setTimeout(function () {
				fn.apply(context, args);
				timer = null;
				/*
为什么不使用clearTimeout?
因为这里需要的是在规定时间内只存在一个定时器在工作,而且使用clearTimeout不易判断是否还存在有计时器
clearTimeout后的timer属于是被弃用的定时器对象,但隐式转换仍会返回true
*/
			}, delay);
		}
	};
}

防抖

js
/* 
为什么这里不使用null?
根据JS的单线程模式,定时器会被认为是宏任务而被放置到宏任务队列等待被处理。
当timer被赋值为定时器时,在宏任务队列中就被存入了一个定时器任务,因此timer=null也仅是将timer的值指向了堆中新存入的null,而宏任务队列中的计时器仍然存在并且会继续执行,除非被clearTimeout清除
*/
function debounce(fn, delay, immediate) {
	let timer;
	return function () {
		const context = this,
			args = arguments;
		if (timer) clearTimeout(timer);
		if (immediate) {
			let callNow = !timer;
			timer = setTimeout(() => {
				timer = null;
			}, delay);
			if (callNow) fn.apply(context, args);
		} else {
			timer = setTimeout(() => {
				fn.apply(context, args);
			}, delay);
		}
	};
}

数组扁平化

js
function flatArr(nums) {
	return nums.reduce((pre, cur) => {
		return pre.concat(Array.isArray(cur) ? flatArr(cur) : cur);
	}, []);
}

手撕 reduce

js
Array.prototype.myReduce = function (callBack, initiate) {
	let arr = this;
	let total = initiate || arr[0];
	for (let i = initiate ? 0 : 1; i < arr.length; i++) {
		total = callBack(total, arr[i], i, arr);
	}
	return total;
};

instanceof 方法

js
function myInstanceof(obj, target) {
	if (typeof obj !== "object" || obj === null) return false;
	if (typeof target !== "function") throw Error("target must be a function");
	let proto = Object.getPrototypeOf(obj);
	while (proto) {
		if (proto === target.prototype) return true;
		proto = Object.getPrototypeOf(proto);
	}
	return false;
}

// 优解
function myInstanceof(obj) {
	if (typeof obj !== "object") return;
	let proto = Object.prototype.toString
		.call(obj)
		.replace(/[\['object (\s.)'\]]/g, "")
		.toLowerCase();
	return proto;
}

快速排序

js
function sortFnc(nums) {
	quickSort(0, nums.length - 1, nums);
	return nums;
}

function quickSort(start, end, arr) {
	if (start < end) {
		let middle = sort(start, end, arr);
		quickSort(start, middle - 1, arr);
		quickSort(middle + 1, end, arr);
	}
}

function sort(left, right, arr) {
	let base = arr[left],
		l = left,
		r = right;
	while (l !== r) {
		while (arr[r] >= base && r > l) {
			r--;
		}
		arr[l] = arr[r];
		while (arr[l] <= base && r > l) {
			l++;
		}
		arr[r] = arr[l];
	}
	arr[l] = base;
	return l;
}

数组去重

js
function myFilter(arr) {
	return arr.filter((value, index, array) => {
		return array.indexOf(value) == index;
	});
}

// 利用Set不可重复特性
function myFilter2(arr) {
	return [...new Set(arr)];
}

async/await实现

js
function asyncToGen(genFunction) {
  return function (...args) {
    const gen = genFunction.apply(this, args);
    return new Promise((resolve, reject) => {
      function step(key, arg) {
        let genResult;
        try {
          genResult = gen[key](arg);
        } catch (err) {
          return reject(err);
        }
        const { value, done } = genResult;
        if (done) {
          return resolve(value);
        }
        return Promise.resolve(value).then(
          (val) => {
            step('next', val);
          },
          (err) => {
            step('throw', err);
          },
        );
      }
      step('next');
    });
  };
}

const getData = () => new Promise(resolve => setTimeout(() => resolve('data'), 1000));

function* testG() {
  const data = yield getData();
  console.log('data: ', data);
  const data2 = yield getData();
  console.log('data2: ', data2);
  return 'success';
}

const gen = asyncToGen(testG);
gen().then(res => console.log(res));