手写call
call
call 函数的实现步骤:
判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
判断传入上下文对象是否存在,如果不存在,则设置为 window 。
处理传入的参数,截取第一个参数后的所有参数。
将函数作为上下文对象的一个属性。
使用上下文对象来调用这个方法,并保存返回结果。
删除刚才新增的属性。
返回结果。
1234567891011121314151617181920 // call函数实现Function.prototype.myCall = function(context) { // 判断调用对象 if (typeof this !== "function") { console.error("type error"); } // 获取参数 let args = [...arguments].slice(1), result = null; // 判断 context 是否传入,如果未传入则设置为 window c ...
手写防抖、节流
防抖、节流
函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。
123456789101112131415161718192021222324 // //防抖function debounce(fn, date) { let timer //声明接收定时器的变量 return function (...arg) { // 获取参数 timer && clearTimeout(timer) // 清空定时器 timer = setTimeout(() => { // 生成新的定时器 //因为箭头函数里的this指向上层作用域的this,所以这里可以直接用this,不需 ...
手写promise(简易版)
promise
12345678910111213141516171819202122232425262728293031323334353637383940class MyPromise { constructor(fn){ // 存储 reslove 回调函数列表 this.callbacks = [] const resolve = (value) => { this.data = value // 返回值给后面的 .then while(this.callbacks.length) { let cb = this.callbacks.shift() cb(value) } } fn(resolve) } then(onResolvedCallback) { return new MyPromise((resolve) => { this.callbacks. ...
手写new
new
首先创建了一个新的空对象
设置原型,将对象的原型设置为函数的 prototype 对象。
让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
123456789101112function myNew(fn, ...args) { // 判断参数是否是一个函数 if (typeof fn !== "function") { return console.error("type error"); } // 创建一个对象,并将对象的原型绑定到构造函数的原型上 const obj = Object.create(fn.prototype); const value = fn.apply(obj, args); // 调用构造函数,并且this绑定到obj上 // 如果构造函数有返回值,并且返回的是对象,就返回value ;否 ...
手写Object.create、instanceof
Object.create
思路:将传入的对象作为原型
12345function create(obj) { function F() {} F.prototype = obj return new F()}
instanceof
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
实现步骤:
首先获取类型的原型
然后获得对象的原型
然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为 null123456789101112function myInstanceof(left, right) { let proto = Object.getPrototypeOf(left), // 获取对象的原型 prototype = right.prototype; // 获取构造函数的 prototype 对象 // 判断构造函数的 prototype 对象是否在对象的原型链上 while (true) { ...
排序算法图解
算法复杂度图示
计数排序算法
计数排序算法算法简介
计数排序是一个分布式排序。分布式排序是使用已经组织好的辅助数据结构(称为 “桶”),来得到排好序的数组。它是用来排序整数的优秀算法(它是一个整数排序算法),但是需要更多的内存来存放临时的数组。
算法分析它主要的流程就是先通过原数组得到一个计数数组,然后通过计数数组恢复出排好序的数组:原数组——>计数数组——>排好序的数组。至于计数数组怎么得到,以及计数数组怎么恢复出原数组的问题,看看下面的例子就知道了。
假设有一个比较常规的数组(数组的最小值是 0,且数组中的每一项都是整数,且数值分布在 0~N 的区间内),常规的计数排序过程是这样的:
因为数组的下标是天然排好序的(从小到大),所以我们进行计数数组的下标与原数组的值进行关联 (这个关联的规律自己心里知道就行)。最简单的关联就是,计数数组下标是 0,则其对应了原数组中的数组值 0。那么此时,计数数组下标的最大值就对应了原数组中的数值的最大值。
找出原数组中的最大值 N,然后创建长度为 N + 1 的计数数组。比如原数组中的最大值为 20,那么计数数组的下标的最大值也要为 20(即数组下标范围:0 ~ ...
基数排序算法
基数排序算法算法简介
基数排序是 1887 年赫尔曼·何乐礼发明的。它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或 bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法(稳定是指相等元素的顺序和原数组中的一直)基数排序(Radix Sort)是桶排序的扩展
算法分析主要思想:
比如:2,22,31,1221,90,85,105
个位排序:90,31,1221,2,22,85,105
十位排序:2,105,1221,22,31,85,90
百位排序:2,22,31,85,90,105,1221
千位排序:2,22,31,85,90,105,1221
注意:每次排序都是在上次排序的基础上进行排序的,也就是说此次排序的位数上他们相对时,就不移动元素(即顺序参数上一个位数的排序顺序)
算法步骤
把所有元素都分配到相 ...
堆排序算法
桶排序算法算法简介
堆是一个完全二叉树。
完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点)。大顶堆:根结点为最大值,每个结点的值大于或等于其孩子结点的值。小顶堆:根结点为最小值,每个结点的值小于或等于其孩子结点的值。堆的存储: 堆由数组来实现,相当于对二叉树做层序遍历。如下图:
对于结点 i ,其子结点为 2i+1 与 2i+2 。
算法描述现在需要对如上二叉树做升序排序,总共分为三步:
将初始二叉树转化为大顶堆(heapify)(实质是从第一个非叶子结点开始,从下至上,从右至左,对每一个非叶子结点做shiftDown操作),此时根结点为最大值,将其与最后一个结点交换。除开最后一个结点,将其余节点组成的新堆转化为大顶堆(实质上是对根节点做shiftDown操作),此时根结点为次最大值,将其与最后一个结点交换。重复步骤2,直到堆中元素个数为1(或其对应数组的长度为1),排序完成。下面详细图解这个过程:
步骤1:初始化大顶堆,首先选取最后一个非叶子结点(我们只需要调整父节点和孩子节点之间的大小关系,叶 ...
桶排序算法
桶排序算法算法简介
说到桶排序,它的思想就是把分治用到极致,把一个序列分为一个个桶,然后对每个桶进行排序,最后再进行整合。
算法描述
确定这个序列要分为几个桶
把每个元素放到对应的桶里面
对每个桶进行排序
对所有的桶进行整合
图解倘若我有这样一个序列
现在我们要确定桶的数量,如和确定呢,这里面有一个计算公式
桶的数量 = (最大值 - 最小值)/ 数组长度 + 1
那这里面我们可以确定桶的数量为 49 / 13 +1 = 4;
现在我们再用另一个公式确定每个元素在哪个桶中
元素位置 =( 元素大小 - 最小值)/ 数组长度
OK,根据这个公式我们可以确定每个元素都在第几个桶里面
现在再对每一个桶进行排序(这里面没有固定的排序算法)
对每个桶进行排序后最后我们进行整合,就变成了一个有序的序列。
代码示例1234567891011121314151617181920212223242526272829 function bucketSort(arr){ let max = Math.max(...arr); let min = Math.min(...arr); ...