ES常用正则

正则对象

正则创建

正则创建有两种方式,对象字面量与构造函数。
使用构造函数 RegExp 创建时接受两个参数。
第一个是要匹配的字符串模式,第二个是可选的标识字符串。
当创建的字符中包含元字符(正则中有特殊含义或功能的字符)时,
要表示原有字符的含义,两种方式创建时都要需要在元字符前使用\进行转义,使其表示为普通含义。
常见的特殊字符有:

[ \ ^ $ . | ? * + ( )

双重转义

阅读全文

数据结构之树

二叉树

二叉树遍历

数据结构之树$20230202135508

深度优先遍历(DFS),根据父节点被访问的次序,分为:

  • 先序遍历(Preorder)

父节点先于左右子树被遍历。
上述二叉树对应结果为

ABDHIEJKCFLG

数据结构之树$20230208112727

  • 中序遍历(Inorder)

父节点遍历次序位于左右子树中间。

HDIBJEKALFCG

数据结构之树$20230208112757

  • 后序遍历(Postorder)

父节点后于左右子树被遍历

HIDJKEBLFGCA

数据结构之树$20230208112821

无论父节点被访问的次序,子树总是先左后右被遍历。

二叉树的深度优先遍历用 Python3 实现如下(对应 leetcode 题目

# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right


class Solution:
# 先序遍历
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ret = []
def traversal(root):
if not root:
return
ret.append(root.val)
if root.left:
traversal(root.left)
if root.right:
traversal(root.right)
traversal(root)
return ret

# 中序遍历
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ret = []
def traversal(root):
if not root:
return
if root.left:
traversal(root.left)
ret.append(root.val)
if root.right:
traversal(root.right)
traversal(root)
return ret
# 后序遍历
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
ret = []
def traversal(root):
if not root:
return
if root.left:
traversal(root.left)
if root.right:
traversal(root.right)
ret.append(root.val)
traversal(root)
return ret

另外还可使用广度优先遍历(BFS),即层次(层序)遍历。
从左到右一层一层访问所有节点

ABCDEFGHIJKL

数据结构之树$20230208112932

层次遍历用 Python 实现如下(对应 leetcode 题目


# @lc code=start
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
# 递归版本
def levelOrderRecursion(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
ret = []
def traversal(preLevel):
level = []
cells = []
for node in preLevel:
cells.append(node.val)
if node.left:
level.append(node.left)
if node.right:
level.append(node.right)
ret.append(cells)
if len(level):
traversal(level)
traversal([root])
return ret

# 双层循环版本
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
ret = []
level = [root]
while len(level):
cells = []
preLevel = level
level = []
for node in preLevel:
cells.append(node.val)
if node.left:
level.append(node.left)
if node.right:
level.append(node.right)
ret.append(cells)
return ret

# 双层循环版本使用队列优化空间
def levelOrderQueue(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
ret = []
level = [root]
while len(level):
cells = []
for _ in range(len(level)):
node = level.pop(0)
cells.append(node.val)
if node.left:
level.append(node.left)
if node.right:
level.append(node.right)
ret.append(cells)
return ret

可以看到,对于变长数组的循环,可以采用while方式进行。

完全二叉树

阅读全文

ES闭包

闭包定义

  • MDN

闭包是指那些能够访问自由变量的函数。

  • JavaScript 权威指南

从技术的角度讲,所有的 JavaScript 函数都是闭包。
在开发实践角度讲,即使创建该函数的上下文已经销毁(父函数执行完毕),该函数仍然存在(比如,内部函数从父函数中返回),该函数中引用了自由变量

自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
可以简单理解为函数外部的变量。

如《JavaScript 权威指南》所说,所有的函数都是闭包。
因为即便是最外层定义的函数,它们也可以访问全局上下文中的自由变量。

定义
《JavaScript 高级程序设计》 闭包是指有权访问另一个’函数’作用域中的变量的函数
《JavaScript 权威指南》 从技术的角度讲,所有的 JavaScript 函数都是闭包
MDN 闭包是指那些能够访问自由变量的函数

闭包可以理解为包含如下要素

  • 函数
  • 自由变量

闭包应用

函数柯里化

阅读全文

Echarts常见使用

Echarts 图表背景图

给图表设定背景图,一般有两种方式,第一种设定 option 中的 graphic

const option = {
graphic: [{
type: 'image', // 图形元素类型
id: 'logo', // 更新或删除图形元素时指定更新哪个图形元素,如果不需要用可以忽略。
right: 'center', // 根据父元素进行定位 (居中)
bottom: '0%', // 根据父元素进行定位 (0%), 如果bottom的值是 0,也可以删除该bottom属性值。
z: 0, // 层叠
bounding: 'all', // 决定此图形元素在定位时,对自身的包围盒计算方式
style: {
// image: "https://www.boxuegu.com/assets/user/background1.png",
width: 945,
height: 800,
},
}, ],
}

另一种方式为直接给图表容器设定背景图。

Echarts 动态柱状图

要让柱状图平滑地向左移动,效果如下:

Echarts常见使用QQ20230317-144305-HD

目前有三个方案。
一是修改x轴和data数据,将数组头部数据放大最末位置然后用setOption刷新图表。
另外两种方案都是使用datazoom来实现。
可以修改datazoom的startValue和endValue然后setOption来刷新图表实现,
目前,echarts已经在API中支持对应的Action,推荐的实现方案如下:

export default {
name: 'DynamicBar',
data() {
return {
startValue: 0,
endValue: 0,
}
},
methods: {
init() {
const dom = document.getElementById('dynamicBar')
this.chart = echarts.init(dom)
},
refresh(option) {
this.chart.setOption(option)
},
},
mounted() {
this.init()
this.refresh(option)
setInterval(() => {
this.startValue++
this.endValue++
this.chart.dispatchAction({
type: 'dataZoom',
startValue: this.startValue % 20, // X轴数据长度为29,坐标轴只显示10条数据,则需要以20为模进行计算
endValue: (this.endValue % 20) + 9,
})
}, 1000)
},
}

option.js

option: {
dataZoom: [
{
show: false,
xAxisIndex: [0],
bottom: 0,
start: 0,
end: 9
},
],
}

Legend 使用

阅读全文

前端工程启动常见包错误

node-sass 错误

项目启动过程报错,
this.getOptions is not a function
styles is not a function
等错误。
造成错误的原因为
node node-sass sass-loader 三者版本不对应。
可尝试如下方案进行解决。
删除关联包

npm uninstall --save sass-loader node-sass

或直接删除 lock 文件与 node_modules
重新安装包。

npm install sass-loader node-sass --save-dev

若使用较老版本 node,可能问题不会解决。
检查包对应关系

NodeJS Supported node-sass version Node Module
Node 20 9.0+ 115
Node 19 8.0+ 111
Node 18 8.0+ 108
Node 17 7.0+ 102
Node 16 6.0+ 93
Node 15 5.0+, <7.0 88
Node 14 4.14+ 83
Node 13 4.13+, <5.0 79
Node 12 4.12+, <8.0 72
Node 11 4.10+, <5.0 67
Node 10 4.9+, <6.0 64
Node 8 4.5.3+, <5.0 57
Node <8 <5.0 <57

详细对应关系见node-sass

sass-loader 与 node-sass 部分对应

sass-loader node-sass
4.1.1 4.3.0
7.0.3 4.7.2
7.3.1 4.14.1
10.0.1 6.0.1

将包对应重新安装。
过程中可能出现 npm rebuild node-sass 等错误提示,按照提示操作。
上述过程操作后仍旧没解决问题,使用

yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass

重新操作上述流程。

node incompatible

The engine "node" is incompatible with this module. Expected version ">= 16". Got "14.17.0"

如果使用的是yarn安装,尝试使用

yarn --ignore-engines

递归

递归调用

递归是一种不使用 for 或者 while 等编程语言预置 API 而实现循环调用的一种编程技巧。
通常实现为函数调用自身。

递归问题的特点为
后续问题为原始问题的简单子问题,可以统一为一个方程求解。
问题需要一个出口。

即其实现的关键是找到

  • 递归方程
  • 递归结束条件

一个简单的正整数求和函数用递归实现如下

const sum = (n) => {
if (n <= 1) return n
return sum(n - 1) + n
}

斐波那契数列递归实现如下

const fibonacci = (n) => {
if (n <= 2) return 1
return fibonacci(n - 1) + fibonacci(n - 2)
}

递归弊端

如 JS 等大多数语言,递归嵌套调用时,会保持跟踪函数执行上下文栈,最外层函数最后执行完成后才会销毁。
在调用sum(10)通过 Chrome 控制台可以看到执行到 n=5 时调用栈如下
递归$20230129145459
这些最底层调用栈最后释放。
当递归过深时通常会导致栈溢出。

Uncaught RangeError: Maximum call stack size exceeded

解决方式通常为尾调用优化和蹦床函数。

尾调用

阅读全文

Git常见问题

Git status 中文展示

在使用git status命令时,若文件名包含中文,可能会出现如下情况
Git常见问题20220506142709
上图框中实际为中文。
输入如下命令解决

git config --global core.quotepath false

或直接在 $HOME/.gitconfig文件中附加

[core]
quotepath = false

Git常见问题20220506142815

文件名过长错误

文件名过长,报错如下:

Filename too long warning: Clone succeeded, but checkout failed.

输入如下命令解决

git config --system core.longpaths true

多个 git 进程

阅读全文


Copyright © 2017 - 2024 鹧鸪天 All Rights Reserved.

skyline 保留所有权利