题目:变量提升/匿名函数this指向
题目:变量提升/匿名函数this指向题目1代码如下:
1234567891011var x = 1, y = 0, z = 0;var add = function (x) { x = x + 1; return x;}y = add(x);function add(x) { return x = x + 3;}z = add(x);console.log(x, y, z);
请问输出的x,y,z的值分别为多少?为什么?
由于函数提升优于变量提升,导致加3的add函数声明被下面加1的add函数表达式覆盖。也就有了下面的代码:
123456789101112131415function add(x) { return x = x + 3;}var x, y, z;var add;x = 1;y = 0;z = 0;add = function (x) { x = x + 1; return x;}y = add(x);z = add(x);console.log(x, y, z);
接着 y = add(x) ...
堆排序&优先级队列
二叉堆本文主要参考二叉堆详解实现优先级队列。对其作者labuladong表示感谢。
说到二叉堆就不得不提到二叉树,在二叉树中有一种特殊的树叫做完全二叉树,而堆就是一种完全二叉树。因此,堆可以用数组来表示。因为完全二叉树的节点之间存在如下关系:
某个节点(其索引为k)的父节点的索引为(k / 2),其左孩子节点索引为2 k,右孩子节点为2 k + 1。正是因为这种关系,才可以用数组来表示堆。
如下图
注:数组的第一个索引 0 空着不用。因为数组索引是数组,为了方便区分,将字符作为数组元素。
可以看到,把arr[1]作为整棵树的根的话,每个节点的父节点和左右孩子节点的索引都可以通过简单的运算得到。
二叉堆还分为最大堆(大顶堆)和最小堆(小顶堆)。最大堆的性质是:每个节点都大于等于它的两个子节点。类似的,最小堆的性质是:每个节点都小于等于它的子节点。
堆主要应用有两个, 首先是一种排序方法「堆排序」, 第二是一种很有用的数据结构「优先级队列」。
堆排序在说堆排序之前,先要知道怎么建堆。常见的方式有两种:
插入式建堆:每次插入一个节点,实现一个大顶堆(或小顶堆)
自下而上式堆化 ...
回溯算法
回溯算法及题目
题号
题目
Tag
39
组合总和
数组、回溯算法
40
组合总和II
数组、回溯算法
46
全排列
数组、回溯算法
51
N皇后
数组、回溯算法
墙裂推荐这篇文章:回溯算法解题套路框架
下面内容大多参考上面这篇文章,对其作者labuladong表示感谢。
回溯算法的框架解决一个回溯问题,实际上就是一个决策树的遍历过程。 只需要思考3个问题:
路径:也就是已经做出的选择
选择列表:也就是当前可以做的选择
结束条件:也就是到达决策树底层,无法再做选择的条件。
在后面的题目中会对这个三个词语再进行解释。
代码方面,回溯算法的框架:
12345678910111213let res = [];function backtrack(路径, 选择列表) { if(满足结束条件) { res.add(路径); return; } //for循环 for (let 选择 in 选择列表) { 做选择 backtrack(路径, 选择列表) 撤销选择 }}
其核心就是for循环里 ...
less内置函数
Less内置函数Logical Functions
if
Examples:
12345@some: foo;div { margin: if((2>1), 0, 3px); color: if((iscolor(@some)), @some, black);}
Result:
1234div { margin: 0; color: black;}
布尔表达式也是支持的:
123if(not (true), foo, bar);if((true) and (2 > 1), foo, bar);if((false) or (isstring("boo!")), foo, bar);
boolean
Example:
1234567@bg: black;@bg-light: boolean(luma(@bg) > 50%);div { background: @bg; color: if(@bg-light, black, white);}
Result:
1234div ...
事件触发器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: ...