最近在复习面试中常见的JS手写函数,顺便进行代码注释和总结,方便自己回顾也加深记,内容也会陆陆续续进行补充和改善。

一、手写深拷贝

    <script>
const obj1 = {
name: 'Leise',
age: 23,
address: {
country: 'China',
city: 'Guanzhou'
}
}
const obj2 = deepClone(obj1)
obj2.address.city = 'Hangzhou'
console.log(obj1.address.city);
console.log(obj2.address.city);

function deepClone(obj) {
//判断是否为非对象或者是null
if (typeof obj !== 'object' || typeof pbj == null) {
return obj
}
// 初始化拷贝结果
let result
// 判断是数组还是对象
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
//保证key不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用深拷贝 防止多重嵌套
result[key] = deepClone(obj[key])
}
}
// 最后返回结果
return result
}
</script>

二、手写bind函数

<script>
Function.prototype.mybind = function () {
//原型添加方法mybind
const args = Array.prototype.slice.call(arguments)
//将获得参数拆解成数组
const t = args.shift()
//获取this(数组第一项,同时剔除第一项,shift可以实现)
const self = this
//当前fn1.bind(...)中的fn1
//console.log(this);
//function fn1(a, b, c) {
//console.log("this", this);
//定义一个变量保留this指向
//console.log(a, b, c); }
return function () {
//console.log(this);window
return self.apply(t, args)
//这个函数需要执行
}
}

function fn1(a, b, c) {
console.log("this", this);
console.log(a, b, c);

}
const fn2 = fn1.mybind({
x: 1,
y: 2
}, 10, 20, )
//bind之后需要执行
const res = fn2()
//保存运行后的结果并打印出来
console.log(res);
</script>

三、手写通用事件绑定函数

<script>
function bindEvent(elem, type, selcetor, fn) {
//判断三个还是四个,四个则是事件代理
if (fn == null) {
fn = selcetor
selcetor = null
}
//开始绑定事件
elem.addEventListener(type, event => {
const target = event.target
//判断是事件代理还是普通绑定
if (selector) {
//事件代理
if (target.matches(selcetor)) {
fn.call(target, event)
} else {
fn.call(target.event)
}
}

})
}

function bindEvent(elem, type, selector, fn) {
// 三个参数和四个参数的判断处理
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {

// 有selector就是代理

if (target.matches(selector)) {
fn.call(target, event)
}
} else {
fn.call(target, event)
}
})
}

const div3 = document.getElementById('div3')
bindEvent(div3, 'click', 'a',
function (event) {
event.preventDefault()
alert(this.innerHTML)

})
</script>

四、手写闭包的简单应用

<script>
function createCache() {
// 闭包隐藏数据,只提供 API
let obj = {}
return {
set: function (key, value) {
obj[key] = value
},
get: function (key) {
return obj[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
obj.d = 100 //undefined,必须使用get或者set
</script>

五、手写promise

    <script>
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = document.createElement('img')
img.src = url
img.onload = () => {
resolve(img)
}
img.onerror = () => {
reject(new Error("图片加载失败"))
}
})
}
const url1 = 'http://img.mukewang.com/5e5c85e1000116c505400720-156-88.jpg'
const url2 = 'https://img.mukewang.com/szimg/5dba8cee0969880506000338.jpg'
loadImg(url1).then((img1) => {
console.log(img1.width);
return img1
}).then((img1) => {
console.log(img1.height);
return loadImg(url2)
}).then(img2 => {
console.log(img2.width);
})
</script>

六、手写Ajax

   <script>
function ajax(url) {
return new Promise((resolve, reject) => {

//判断谷歌等还是IE
let xhr
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest()

} else { // code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP")
}
// xhr 具有一个 open 方法,这个方法的作用类似于初始化,并不会发起真正的请求
// open 方法具有 5 个参数,但是常用的是前 3 个
// method: 请求方式 —— get / post
// url:请求的地址
// async:是否异步请求,默认为 true(异步)
xhr.open("get", url, true)
// send 方法发送请求,并接受一个可选参数
// 当请求方式为 post 时,可以将请求体的参数传入
// 当请求方式为 get 时,可以不传或传入 null
// 不管是 get 还是 post,参数都需要通过 encodeURIComponent 编码后拼接
xhr.send(null)
//当readyStatus的状态发生改变时,会触发 xhr 的事件onreadystatechange
xhr.onreadystatechange = () => {
//readyStatus: 请求/响应过程的当前活动阶段
if (xhr.readyState == 4) {
//HTTP 状态在 200-300 之间表示请求成功
// HTTP 状态为 304 表示请求内容未发生改变,可直接从缓存中读取
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {

let obj = JSON.parse(xhr.responseText)
// console.log(obj)
// callBack(obj)
resolve(obj)
} else {
reject(new Error("错误"))
}
}
}
})
}
const url1 = "http://jsonplaceholder.typicode.com/users"
const url2 = "/a.json"
const url3 = "/b.json"

ajax(url1).then(res => {
console.log(res);
return ajax(url2)
}).then(res => {
console.log(res);
return ajax(url3)
}).then(() => {
console.log("ok");
}).catch((res) => {
console.log(res) //设置一个统一出口 如果出现错误就终止
})
</script>

七、手写防抖

   <script>
const input1 = document.getElementById('input1')

function debounce(fn, delay) {
//timer必须在闭包中 才不会被外面修改
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay);
}
}
input1.addEventListener('keyup', debounce(function () {
console.log(input1.value);
}, 500))
</script>

八、手写节流

<script>
function throttle(fn, delay) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null++
}, delay);
}
}
const one = document.getElementById('one')
one.addEventListener('drag', throttle(function (e) {
console.log(e.offsetX, e.offsetY);
}, 1000))
</script>

常见的JS手写函数汇总(代码注释、持续更新)的更多相关文章

  1. 4.redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

    作者:中华石杉 面试题 redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现? 面试官心理分析 如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当 ...

  2. redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现?

    redis的过期策略都有哪些? 设置过期时间: set key 的时候,使用expire time,就是过期时间.指定这个key比如说只能存活一个小时?10分钟?指定缓存到期就会失效. redis的过 ...

  3. 原生html、js手写 radio与checkbox 美化

    原生html.js手写 radio与checkbox   美化 html <!DOCTYPE html> <html> <head> <meta charse ...

  4. # OpenGL常用函数详解(持续更新)

    OpenGL常用函数详解(持续更新) 初始化 void glutInit(int* argc,char** argv)初始化GULT库,对应main函数的两个参数 void gultInitWindo ...

  5. 五四青年节,今天要学习。汇总5道难度不高但可能遇到的JS手写编程题

    壹 ❀ 引 时间一晃,今天已是五一假期最后一天了,没有出门,没有太多惊喜与意外.今天五四青年节,脑子里突然想起鲁迅先生以及悲欢并不相通的话,我的五一经历了什么呢,忍不住想说那大概是,父母教育孩子大声嚷 ...

  6. 手写算法-python代码实现KNN

    原理解析 KNN-全称K-Nearest Neighbor,最近邻算法,可以做分类任务,也可以做回归任务,KNN是一种简单的机器学习方法,它没有传统意义上训练和学习过程,实现流程如下: 1.在训练数据 ...

  7. 按“块”的方式写dom以及代码注释

    前言 首先这个文档中主要记述了自己在编写html代码时如何构建良好的dom结构的一些所思所想,在这一部分主要说明按“块”构建dom结构的思路.同时在这篇文档中也记述了自己对代码注释的理解,在这一部分主 ...

  8. 浅谈时钟的生成(js手写代码)

    在生成时钟的过程中自己想到布置表盘的写法由这么几种: 当然利用那种模式都可以实现,所以我们要用一个最好理解,代码有相对简便的方法实现 1.利用三角函数 用js在三角函数布置表盘的过程中有遇见到这种情况 ...

  9. 浅谈时钟的生成(js手写代码)(非原创)

    在生成时钟的过程中自己想到布置表盘的写法由这么几种: 当然利用那种模式都可以实现,所以我们要用一个最好理解,代码有相对简便的方法实现 1.利用三角函数 用js在三角函数布置表盘的过程中有遇见到这种情况 ...

随机推荐

  1. Mybatis【1】-- 第一个Mybatis程序

    1.框架是什么 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架.前者是从应用方面而后者是从目的方面 ...

  2. 在windows环境下 nginx + .net core 3.1 实现反向代理和负载均衡

    一.创建.net core web 应用 1.首先打开vs2019创建好.net core web应用,简单的注入IConfiguration 便于打印端口号展示效果. 1 private reado ...

  3. 记安装Wampsever

    遇到的问题: Wampsever 启动所有服务后图标为黄色 localhost 问题:显示 IIS Windows 在用 localhost 访问本机的php文件和用ip地址(不是127.0.0.1) ...

  4. 【NOIP2017提高A组模拟9.17】猫

    [NOIP2017提高A组模拟9.17]猫 题目 Description 信息组最近猫成灾了! 隔壁物理组也拿猫没办法. 信息组组长只好去请神刀手来帮他们消灭猫.信息组现在共有n 只猫(n 为正整数) ...

  5. NOIp2020游记

    Day 1 考点还是在南航,第三次去已经没有什么新鲜感了,满脑子都是NOIp能不能考好.考前奶了一波这次必考最短路,于是在试机的时候打了一遍Dij和SPFA的板子,信心满满的上场了. 考试右后方是Ki ...

  6. 并发编程实战-J.U.C核心包

    J.U.C - AQS java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J.U.C 的核心.它核心是利用volatile和一个维护队列. AQS其实就是ja ...

  7. 第4.7节 Python特色的序列解包、链式赋值、链式比较

    一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...

  8. PyQt(Python+Qt)学习随笔:QDateTimeEdit日期时间编辑部件

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 Designer输入部件中,Date/Time E ...

  9. PyQt学习随笔:重写setData方法截获Model/View中视图数据项编辑的注意事项

    根据<PyQt学习随笔:Model/View中视图数据项编辑变动实时获取变动数据的方法>可以重写从PyQt的Model类继承的setData方法来实时截获View中对数据的更改,但需要注意 ...

  10. JMeter断言/检查点

    断言就类似LoadRunner中的检查点.对上一个请求返回的信息,获取部分字符串.图片等做判断,确保返回的信息的准确性. 右键点击"HTTP请求" -> "添加&q ...