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;}
实现数组的filter方法
实现数组的filter方法
123456789101112Array.prototype._filter = function(fn) { if (typeof fn !== "function") { throw Error('参数必须是一个函数'); } const res = []; for (let i = 0, len = this.length; i < len; i++) { fn(this[i]) && res.push(this[i]); } return res;}
实现数组的push方法
实现数组的push方法
123456789let arr = [];Array.prototype.push = function() { for( let i = 0 ; i < arguments.length ; i++){ this[this.length] = arguments[i] ; } return this.length;}
实现数组的flat方法
实现数组的 flat 方法
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。 其中,depth 指定要提取嵌套数组的结构深度,默认值为 1。但使用 Infinity 作为深度,展开任意深度的嵌套数组
12345678910111213function _flat(arr, depth) { if(!Array.isArray(arr) || depth <= 0) { return arr; } return arr.reduce((prev, cur) => { if (Array.isArray(cur)) { return prev.concat(_flat(cur, depth - 1)) } else { return prev.concat(cur); } }, []);}
实现数组扁平化
实现数组扁平化
通过循环递归的方式,一项一项地去遍历,如果每一项还是一个数组,那么就继续往下遍历,利用递归程序的方法,来实现数组的每一项的连接:
12345678910111213141516let arr = [1, [2, [3, 4, 5]]];function flatten(arr) { let result = []; for(let i = 0; i < arr.length; i++) { if(Array.isArray(arr[i])) { result = result.concat(flatten(arr[i])); } else { result.push(arr[i]); } } return result;}flatten(arr); // [1, 2, 3, 4,5]
或者
1let newArray = arr.flat(depth)
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历 ...