事件触发器EventEmitter
事件触发器EventEmitter发布订阅模式:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849class EventEmitter { constructor() { this._event = [] } on(eventName, fn) { let callback = this._event[eventName] || []; callback.push(fn); this._event[eventName] = callback; return this; } emit(...args) { let eventName = args[0]; let params = args.slice(1); let event = this._event[eventName]; event.forEach(fn => fn.appl ...
函数防抖和节流、以及Promise.all实现
函数防抖和节流、以及Promise.all实现防抖
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
1234567891011121314function debounce(fn, time) { let _t; return function () { clearTimeout(_t); _t = setTimeout(() => { fn(); }, time) }}function handleresize() { console.log(1);}window.onresize = debounce(handleresize, 5000);
节流
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
12345678910111213function throttle(fn, delay) { let currentTime = new Date ...
JS原生函数模拟实现new和instanceof及函数柯里化
JS原生函数模拟实现new和instanceofnew的模拟实现首先要知道new操作符,在new 一个构造函数时,发生了什么:
创建一个新对象
将这个新对象的隐式原型(__proto__)指向构造函数的原型(prototype)
将构造函数的属性和方法添加到这个新对象中
返回这个新对象
ps:如果构造函数返回的是对象或者是函数则在new运算符调用这个构造函数时返回的是对象或者函数。
代码实现如下:
12345678910function _new(...args) { let constructor = args[0]; let obj = Object.create(constructor.prototype);//把前两步完成啦 let res = constructor.call(obj, ...args.slcie(1));//完成第三步 if((typeof res === 'object' || typeof res === 'function') && res !== null) { ...
CommonJS 与 ES6 Module的区别
CommonJS 与 ES6 Module的区别
主要参考书籍:《webpack实战:入门、进阶与调优》(微信读书)
静态和动态cjs与esm最本质的区别在于前者对模块依赖的解决是“动态的”。而后者是“静态的”。在这里“动态”的含义是,模块依赖关系的建立发生在代码运行阶段;而“静态”则是模块依赖关系的建立发生在代码编译阶段。
先看一个cjs的例子
1234567//calculator.jsmodule.exports = { name: 'calculator'};//index.jsconst name = require('./calculator.js').name
当index.js加载calculator.js时,会执行calculator.js中的代码,并将其module.exports对象作为require函数的返回值进行返回。并且require的模块路径可以动态指定,支传入一个表达式,我们甚至可以通过if语句判断是否加载某个模块。因此,在cjs模块被执行前,并没有办法确定明确的依赖关系,模块的导入、导出发 ...
ES5/6对象的继承及区别
ES5/6对象的继承ES5的对象继承(组合继承)12345678910111213141516171819202122232425262728function user(name, age) { this.name = name; this.age = age; } user.prototype.sayName = function () { console.log(this.name); } function vipuser(name, age, level) { user.call(this, name, age); this.level = level; } vipuser.prototype = new user(); vipuser.prototype.constructor = vipuser; vipuser.prototype.saylevel = function () { console.log(this.level); } console.log(Reflect ...
元素垂直水平居中的几种方法
元素垂直水平居中的几种方法HTML:
123<body> <div></div></body>
方法1:12345678910111213141516body { width: 100%; height: 100vh; border: 1px solid blue;}body div { height: 100px; width: 100px; background-color: red; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto;}
方法2:123456789101112body { width: 100%; height: 100vh; border: 1px solid blue; display: flex;}body div { height: 100px; width: 100px; background-color: ...
239.滑动窗口最大值
239.滑动窗口最大值描述给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
示例
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
-——————— —————
[1 3 -1] -3 5 3 6 7 => 3
1 [3 -1 -3] 5 3 6 7 => 3
1 3 [-1 -3 5] 3 6 7 => 5
1 3 -1 [-3 5 3] 6 7 => 5
1 3 -1 -3 [5 3 6] 7 => 6
1 3 -1 -3 5 [3 6 7] => 7
代码及思路思路其实开始感觉这个题目没啥难度,不知道为啥是困难 ...
JS原生函数实现之数组实例方法map/reduce
JS原生函数实现之数组实例方法map/reduce
123456789101112Array.prototype.map2 = function (fn, thisVal) { if (typeof fn != 'function') { throw new Error(fn + 'should be function'); } if (this.length == 0) { return []; } return this.reduce((arr, curVal, curIndex) => { arr.push(fn.call(thisVal, curVal, curIndex, this)); return arr; }, [])};
1234567Array.prototype.reduce2 = function (callback, initData) { let initVal = initData ...
JS原生函数实现之call、apply、bind
JS原生函数实现之call/apply/bind1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374let foo = { a: 10}function bar(name, age) { console.log(name, age); console.log(this.a);}/*let foo = { a: 10, bar: function(name,age) { console.log(name, age); console.log(this.a); }}foo.bar();//10*/Function.prototype.call2 = function (context) { let _context = context || window ...
1103.分糖果II
1103.分糖果II描述排排坐,分糖果。
我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。
给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。
然后,我们再回到队伍的起点,给第一个小朋友 n + 1 颗糖果,第二个小朋友 n + 2 颗,依此类推,直到给最后一个小朋友 2 * n 颗糖果。
重复上述过程(每次都比上一次多给出一颗糖果,当到达队伍终点后再次从队伍起点开始),直到我们分完所有的糖果。注意,就算我们手中的剩下糖果数不够(不比前一次发出的糖果多),这些糖果也会全部发给当前的小朋友。
返回一个长度为 num_people、元素之和为 candies 的数组,以表示糖果的最终分发情况(即 ans[i] 表示第 i 个小朋友分到的糖果数)。
示例
示例 1:
输入:candies = 7, num_people = 4
输出:[1,2,3,1]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0,0]。
第 ...