文章目录
- 深拷贝
- 柯里化函数
- 实现 instanceof
- 手写 new
- 数组去重
- flat 拍平数组
- ObjectDefineProperty实现双向数据绑定
- setInterval 实现 setTimeout
- setTimeout 实现 setInterval
- this 绑定 apply,call,bind
- apply
- call
- bind
- 手写 promise
- promissAll
- promiseFinally
- promiseRace
- promiseReject
- prmiseResole
- 防抖,节流
- 排序算法
- 快速排序
- 选择排序
- 插入排序
- 归并排序
- 冒泡排序
- 希尔排序
- 继承
- 原型链继承
- 构造函数继承
- 组合继承(原型链继承 + 构造函数继承)
- 原型式继承
- 寄生式继承
- 组合寄生式继承
- ES6 继承
- 算法题
- 大数相加
- 哈夫曼树
- 千分位分隔符
- 最大公约数
深拷贝
function deepClone(obj = {}) {
if (typeof obj !== "object" && obj !== null) return obj;
let result = obj instanceof Array ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
let obj = {
name: "kunyuan",
age: 15,
da: {
name: "45",
},
};
let newObj = deepClone(obj);
newObj.name = "laj";
newObj.da.name = "aaaaaaaa";
console.log(obj);
console.log(newObj);
<img src="" alt="" width="30%" />
柯里化函数
let sum = (a, b, c, d) => {
return a + b + c + d;
};
let curry = (fn,...args) => {
return args.length >= fn.length ? fn(...args) : (...arr)=> curry(fn,...args.concat(...arr))
}
var sumPlus = curry(sum);
console.log(sumPlus(1)(2)(3)(4));
console.log(sumPlus(1, 2)(3)(4));
console.log(sumPlus(1, 2, 3)(4));
实现 instanceof
function myInstanceOf(left, right) {
let leftValue = left.__proto__;
let rightValue = right.prototype;
while (true) {
if (leftValue == null) return false;
if (leftValue === rightValue) {
return true;
}
leftValue = leftValue.__proto__;
}
}
function getType(type) {
return Object.prototype.toString.call(type).slice(8, -1);
}
console.log(myInstanceOf(Object, Function));
console.log(getType(1));
手写 new
function mynew(func, ...args) {
let obj = {};
obj.__proto__ = func.prototype;
let result = func.apply(obj, args);
return result instanceof Object ? result : obj;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(this.name + ' ' + this.age);
}
let p = mynew(Person, "邬坤源", 12);
console.log(p);
p.say();
数组去重
var array = [1, 2, 1, 1, '1'];
function uniques(array){
return Array.from(new Set(array));
}
function SampleUniques(array){
return [...new Set(array)]
}
console.log(uniques(array));
function es5Uniques(array){
let res = array.filter(function(item,index,array){
return array.indexOf(item) === index;
})
return res;
}
console.log("es5去重");
console.log(es5Uniques(array));
flat 拍平数组
const arr = [1, [2, 3, [4, [[5]]]]]
console.log(arr.flat(1));
console.log(arr.flat(2));
console.log(arr.flat(3));
console.log(arr.flat(4));
console.log("depth<=0时,返回的数组和原数组维数一样(注意只是维数一样,空位情况见第3点)");
console.log(arr.flat(0));
console.log([].concat(...arr));
function myflat(arr){
while(arr.some(item=>Array.isArray(item))){
arr = [].concat(...arr)
}
return arr;
}
console.log("我的实现");
console.log(myflat(arr));
Array.prototype.newflat = function(n=1){
let arr = this;
while(n && this.some(item=>Array.isArray(item))){
arr = [].concat(...arr);
n--;
}
return arr;
}
console.log("重写原型上的方法");
console.log([1, 2, [3, 4, [5, [6, [7]]]]].newflat(5))
function FlatReduce(arr){
return arr.reduce((pre,cur) => {
return pre.concat(Array.isArray(cur)?FlatReduce(cur):cur)
},[])
}
ObjectDefineProperty实现双向数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" value="" name="txt" id="txt">
<p id="Show_text"></p>
</div>
<script>
var obj = {};
Object.defineProperty(obj, 'value', {
get: function () {
return obj;
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('Show_text').innerHTML = newValue
},
})
document.addEventListener('keyup', function (e) {
obj.value = e.target.value
})
</script>
</body>
</html>
setInterval 实现 setTimeout
const mySetTimeout = (fn, delay) => {
const timer = setInterval(() => {
fn()
clearInterval(timer)
}, delay)
}
setTimeout 实现 setInterval
const mySetInterval = (fn, delay) => {
let timer = null
const interval = () => {
fn()
timer = setTimeout(interval, delay)
}
timer = setTimeout(interval, delay)
return {
cancel: () => {
clearTimeout(timer)
}
}
}
this 绑定 apply,call,bind
apply
Function.prototype.myApply = function(context=globalThis,...args){
let key = Symbol('key');
context[key] = this;
let result = context[key](args);
delete context[key];
return result;
}
function f(a,b){
console.log(a+b)
console.log(this.name)
}
let obj={
name:'张三'
}
f.myApply(obj,[1,2])
call
Function.prototype.newCall = function(context=globalThis,...args) {
let key = Symbol('key')
context[key] = this
let result = context[key](...args)
delete context[key]
return result;
}
function f(a,b){
console.log(a+b)
console.log(this.name)
}
let obj={
name:1
}
f.newCall(obj,1,2)
bind
const obj = {
name: "11",
fun() {
console.log(this.name);
},
};
Function.prototype._bind = function (ctx, ...args) {
const _self = this;
const bindFn = (...reset) => {
return _self.call(ctx, ...args, ...reset);
};
return bindFn;
};
const obj2 = { name: "22" };
obj.fun();
const fn = obj.fun.bind(obj2);
const fn2 = obj.fun._bind(obj2);
fn();
fn2();
手写 promise
promissAll
function promiseAll(promises){
if(!Array.isArray(promises)){
throw new TypeError("promises must be an array")
}
return new Promise(function(resolve, reject){
let promiseNum = promises.length;
let resolveCount = 0;
let resolveValues = new Array(promiseNum);
for(let i=0; i<promiseNum; i++){
Promise.resolve(promises[i]).then(function(value){
resolveValues[i] = value;
resolveCount++;
if(resolveCount == promiseNum){
return resolve(resolveValues)
}
},
function(err){
return reject(err);
}
)
}
})
}
promiseFinally
Promise.prototype.finally = function(callback) {
this.then(value => {
return Promise.resolve(callback()).then(() => {
return value;
})
}, error => {
return Promise.resolve(callback()).then(() => {
throw error;
})
})
}
promiseRace
function PromiseRace(promises) {
if(promises instanceof Array){
throw new TypeError("promises must be an array")
}
return new Promise(function(resole,reject){
promises.forEach( item =>{
Promise.resolve(item).then(data=>{
resole(data)
},
err =>{
reject(err)
}
)
})
})
}
promiseReject
Promise.reject = function(reason){
return new Promise((resolve, reject)=>reject(reason))
}
prmiseResole
Promise.resolve = function(value) {
if(value instanceof Promise){
return value;
}
return new Promise((resolve, reject)=>resolve(value))
}
防抖,节流
const debounce = (func,wait = 500) => {
var timer = 0;
return function(...args) {
if(timer) clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(this,args);
},wait);
}
}
const fn = debounce(()=>{console.log(3);},3000)
setInterval(fn, 2000)
const throttle = (func, wait = 500) => {
let lastTime = 0
return function (...args) {
let now = +new Date()
if (now - lastTime > wait) {
lastTime = now
func.apply(this, args)
}
}
}
const fn = throttle(() => {
console.log(3);
}, 3000)
setInterval(fn, 2000)
排序算法
快速排序
function QuickSort(arr) {
const n = arr.length;
if (n <= 1) return arr;
let pivot = arr[0];
let left = [];
let right = [];
for (let i = 1; i < n; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return [...QuickSort(left), pivot, ...QuickSort(right)]
}
let list = [4, 6, 8, 5, 9, 1, 2, 3, 2];
let sortArr = QuickSort(list)
console.log("快速排序", sortArr);
选择排序
function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
插入排序
function insertionSort(arr) {
var len = arr.length;
var preIndex, current;
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = current;
}
return arr;
}
归并排序
const mergeSort = arr => {
const len = arr.length;
if (len < 2) {
return arr;
}
let middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
};
const merge = (left, right) => {
const result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length) result.push(left.shift());
while (right.length) result.push(right.shift());
return result;
};
const arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
console.time('归并排序耗时');
console.log('arr :', mergeSort(arr));
console.timeEnd('归并排序耗时');
冒泡排序
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
希尔排序
function shellSort(arr) {
let length = arr.length
let interval = Math.floor(length / 2)
while (interval >= 1) {
for (let i = interval; i < length; i++) {
let temp = arr[i]
let j = i
while (arr[j - interval] > temp && j - interval >= 0) {
arr[j] = arr[j - interval]
j -= interval
}
arr[j] = temp
}
interval = Math.floor(interval / 2)
}
return arr
}
继承
原型链继承
function Parent(){
this.name = '邬坤源',
this.play = [1,2,3]
}
function Child(){
this.age = 29
}
Child.prototype = new Parent();
let myChild = new Child();
console.log(myChild.name);
var s1 = new Child();
var s2 = new Child();
s1.play.push(4);
console.log(s1.play, s2.play);
构造函数继承
function Parent(){
this.name = 'parent1';
}
Parent.prototype.getName = function () {
return this.name;
}
function Child(){
Parent.call(this);
this.type = 'child'
}
let child = new Child();
console.log(child);
console.log(child.getName());
组合继承(原型链继承 + 构造函数继承)
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
Parent3.prototype.getName = function () {
return this.name;
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
console.log(s3.getName());
console.log(s4.getName());
原型式继承
这里主要借助Object.create方法实现普通对象的继承
let parent = {
name: 'li',
friends: ['ha','mo','gui'],
getName:function(){
return this.name;
}
}
let person = object.create(parent);
person4.name = "tom";
person4.friends.push("jerry");
console.log(person4.name);
console.log(person4.name === person4.getName());
let person5 = Object.create(parent4);
person5.friends.push("lucy");
console.log(person5.name);
console.log(person4.friends);
console.log(person5.friends);
寄生式继承
let parent5 = {
name: "parent5",
friends: ["p1", "p2", "p3"],
getName: function() {
return this.name;
}
};
function clone(original) {
let clone = Object.create(original);
clone.getFriends = function() {
return this.friends;
};
return clone;
}
let person5 = clone(parent5);
console.log(person5.getName());
console.log(person5.getFriends());
组合寄生式继承
function Parent6() {
this.name = 'parent6';
this.play = [1, 2, 3];
}
Parent6.prototype.getName = function () {
return this.name;
}
function Child6() {
Parent6.call(this);
this.friends = 'child5';
}
function clone (parent, child) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
}
clone(Parent6, Child6);
Child6.prototype.getFriends = function () {
return this.friends;
}
let person6 = new Child6();
console.log(person6);
console.log(person6.getName());
console.log(person6.getFriends());
ES6 继承
class Person {
constructor(name) {
this.name = name
}
getName = function () {
console.log('Person:', this.name)
}
}
class Gamer extends Person {
constructor(name, age) {
super(name)
this.age = age
}
}
const asuna = new Gamer('Asuna', 20)
asuna.getName()
算法题
大数相加
console.log(Number.MAX_SAFE_INTEGER)
console.log(Number.MIN_SAFE_INTEGER)
let a = "9007199254740991", b = '1234567899999999999'
function add(a, b) {
const MAX_LEN = Math.max(a.length, b.length)
a = a.padStart(MAX_LEN, 0)
b = b.padStart(MAX_LEN, 0)
let flag = 0
let str = '', j = MAX_LEN-1
while(j >= 0) {
let res = Number(a[j]) + Number(b[j]) + flag
flag = res >= 10 ? 1 : 0
res = res % 10
str = res + str
j--
}
if(flag === 1) {
str = '1' + str
}
return str
}
console.log(add(a, b))
哈夫曼树
function TreeNode(val, char, left, right) {
this.val = val || 0
this.char = char || ''
this.left = left || null
this.right = right || null
}
function HuffmanTree(str) {
if(str === '') { return null }
let hash = {}
for(let i=0; i<str.length; i++) {
hash[str[i]] ??= 0
hash[str[i]] = hash[str[i]] + 1
}
const huffmanTree = this.getHuffmanTree(hash)
console.log('===哈夫曼树===', huffmanTree)
const map = this.getHuffmanCode(huffmanTree)
console.log('===哈夫曼编码表===', map)
let res = ''
for(let item in hash) {
res += map.get(item)
}
console.log('===哈夫曼总编码===', res)
}
HuffmanTree.prototype.getHuffmanTree = function(hash) {
let forest = []
for(let char in hash) {
const node = new TreeNode(hash[char], char)
forest.push(node)
}
console.log(forest)
let allNodes = []
while(forest.length != 1) {
forest.sort((a, b) => a.val - b.val)
let node = new TreeNode(forest[0].val + forest[1].val)
allNodes.push(forest[0])
allNodes.push(forest[1])
node.left = allNodes[allNodes.length - 2]
node.right = allNodes[allNodes.length - 1]
forest = forest.slice(2)
forest.push(node)
}
return forest[0]
}
HuffmanTree.prototype.getHuffmanCode = function(huffmanTree) {
let map = new Map()
const search = (node, curPath) => {
if(!node) { return }
if(!node.left && !node.right) {
map.set(node.char, curPath)
}
if(node.left) {
search(node.left, curPath + '0')
}
if(node.right) {
search(node.right, curPath + '1')
}
}
search(huffmanTree, '')
return map
}
const huff = new HuffmanTree('ABBCCCDDDDEEEEE')
千分位分隔符
var throusandDot = function(num) {
num = String(num)
let [zheng, xiao] = num.split('.')
console.log(zheng, xiao)
let sum = 0, res = []
for(let i=zheng.length-1; i>=0; i--) {
res.push(zheng[i])
sum++
if(sum === 3 && i!=0) { res.push(','); sum = 0 }
}
return res.reverse().join('') + '.' + xiao
}
console.log(throusandDot(119351235.235767))
var throusandDot = function(num) {
return num.toLocaleString()
}
console.log(throusandDot(119351235.235767))
var throusandDot = function(num) {
var res=num.toString().replace(/\d+/, function(n){
return n.replace(/(\d)(?=(\d{3})+$)/g, function($1){
return $1+",";
});
})
return res;
}
console.log(throusandDot(119351235.235767))
最大公约数
function greatestCommonDivisor(a, b) {
if(b == 0) {
return a
}
return greatestCommonDivisor(b, a % b)
}
function greatestCommonDivisor2(a, b) {
if(a > b) {
a -= b
} else if(a < b) {
b -= a
} else {
return a
}
}
更多算法实现可移步我的 GitHub,欢迎 start
https://github.com/tomato-wu/JS-algorithm.git
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)