实现 jsonp
实现 jsonp
123456789101112131415// 动态的加载js文件function addScript(src) { const script = document.createElement('script'); script.src = src; script.type = "text/javascript"; document.body.appendChild(script);}addScript("http://xxx.xxx.com/xxx.js?callback=handleRes");// 设置一个全局的callback函数来接收回调结果function handleRes(res) { console.log(res);}// 接口返回的数据格式handleRes({a: 1, b: 2});
使用setInterval实现setTimeout
使用setInterval实现setTimeout
实现思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果
1234567891011function mySetInterval(fn, t) { const timer = setInterval(() => { clearInterval(timer) fn() }, t) mySetInterval(() => { console.log('hoho'); }, 1000)}
使用 setTimeout 实现 setInterval
使用 setTimeout 实现 setInterval
实现思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果
123456789101112131415161718function mySetInterval(fn, timeout) { // 控制器,控制定时器是否继续执行 var timer = { flag: true }; // 设置递归函数,模拟定时器执行。 function interval() { if (timer.flag) { fn(); setTimeout(interval, timeout); } } // 启动定时器 setTimeout(interval, timeout); // 返回控制器 return timer;}
实现路由(简易版)
实现路由(简易版)
123456789101112131415161718192021222324// hash路由class Route{ constructor(){ // 路由存储对象 this.routes = {} // 当前hash this.currentHash = '' // 绑定this,避免监听时this指向改变 this.freshRoute = this.freshRoute.bind(this) // 监听 window.addEventListener('load', this.freshRoute, false) window.addEventListener('hashchange', this.freshRoute, false) } // 存储 storeRoute (path, cb) { this.routes[path] = cb || function ( ...
Proxy数据劫持(简易版)
Proxy数据劫持(简易版)
1234567891011121314151617181920212223242526// Vue3的数据劫持通过Proxy函数对代理对象的属性进行劫持,通过Reflect对象里的方法对代理对象的属性进行修改,// Proxy代理对象不需要遍历,配置项里的回调函数可以通过参数拿到修改属性的键和值// 这里用到了Reflect对象里的三个方法,get,set和deleteProperty,方法需要的参数与配置项中回调函数的参数相同。// Reflect里的方法与Proxy里的方法是一一对应的,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。 const obj = { name: '刘逍', age: 20 } const p = new Proxy(obj, { // 读取属性的时候会调用getter get(target, propName) { //第一个参数为代理的源对象,等同于上面的Obj参数。第二个参数为读取的那个属性值 ...
Object.defineProperty(简易版)
Object.defineProperty(简易版)
1234567891011121314151617181920212223// Vue2的响应式原理,结合了Object.defineProperty的数据劫持,以及发布订阅者模式// Vue2的数据劫持,就是通过递归遍历data里的数据,用Object.defineProperty给每一个属性添加getter和setter,// 并且把data里的属性挂载到vue实例中,修改vue实例上的属性时,就会触发对应的setter函数,向Dep订阅器发布更新消息,// 对应的Watcher订阅者会收到通知,调用自身的回调函数,让编译器去更新视图。 const obj = { name: '刘逍', age: 20 } const p = {} for (let key in obj) { Object.defineProperty(p, key, { get() { cons ...
手写发布-订阅模式
手写发布-订阅模式
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748class EventCenter{ // 1. 定义事件容器,用来装事件数组 let handlers = {} // 2. 添加事件方法,参数:事件名 事件方法 addEventListener(type, handler) { // 创建新数组容器 if (!this.handlers[type]) { this.handlers[type] = [] } // 存入事件 this.handlers[type].push(handler) } // 3. 触发事件,参数:事件名 事件参数 dispatchEvent(type, params) { // 若没有注册该事件则抛出错误 if (!this.handlers[type]) ...
用Promise实现图片的异步加载
用Promise实现图片的异步加载
123456789101112131415161718192021let imageAsync=(url)=>{ return new Promise((resolve,reject)=>{ let img = new Image(); img.src = url; img.οnlοad=()=>{ console.log(`图片请求成功,此处进行通用操作`); resolve(image); } img.οnerrοr=(err)=>{ console.log(`失败,此处进行失败的通用操作`); reject(err); } })} imageAsync("url").then(()=>{ console.log("加载成功");}).catch( ...
add(1)(2)(3)(4)
add(1)(2)(3)(4)
可以实现任意数量数字相加,但是需要用+号隐式转换
12345678910111213141516function fn() { let result = []; function add(...args) { // ...args剩余参数,可以获取到传进来的参数 result = [...result, ...args] return add; }; // 创建一个取代 valueOf 方法的函数,覆盖自定义对象的 valueOf 方法 add.toString = () => result.reduce((sum, k) => sum + k, 0); return add;};let add = fn() console.log(+add(1)(2)(3)(4)) // --->10 // let add2 = fn(); console.log(+add2(1, 2, 3)(4)) // --->10
参数固定的情况下,不需 ...
实现数组的map方法
实现数组的filter方法
1234567891011Array.prototype._map = function(fn) { if (typeof fn !== "function") { throw Error('参数必须是一个函数'); } const res = []; for (let i = 0, len = this.length; i < len; i++) { res.push(fn(this[i])); } return res;}