我是瘦子


  • 首页

  • 归档

  • 标签

  • 搜索
close
我是瘦子

JavaScript 针对特殊符号或emoji表情的正则判断

发表于 2020-10-21 | 阅读次数

记录一些常用的正则到博客中。

1
2
3
4
5
6
7
8
// 判断是否含有特殊符号
let iconRule1 = /[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/im
// 判断是否含有emoji表情
let iconRule2 = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/ig
// 如果为true,字符串含有emoji表情 ,false不含
console.log(iconRule2.test('😺')); // true
// 如果为true,字符串含有特殊符号 ,false不含
console.log(iconRule1.test('【】')) // true
我是瘦子

JavaScript 相关算法

发表于 2020-09-30 | 阅读次数

冒泡排序

冒泡排序的思路:遍历数组,然后将最大数沉到最底部;
时间复杂度:O(N^2);
空间复杂度:O(1)

作为最简单的排序算法之一,冒泡排序的思想是,从左到右依次比较两个存储数据的大小,如果第一个数大于第二个数,就交换两个数据,这样一轮比较之后,最大的数会放在后面,这样,每次循环比较,本轮中的最大值都会排到最后,直到循环结束,实现数组升序。
动图演示如下:
冒泡排序动画演示

阅读全文 »
我是瘦子

JavaScript 中文首字母排序

发表于 2020-09-25 | 阅读次数

String

String.prototype.localeCompare()

引自MDN:localeCompare() 方法返回一个数字来指示一个参考字符串是否在排序顺序前面或之后或与给定字符串相同。

语法

1
2
// referenceStr:引用字符串    compareString:比较字符串
referenceStr.localeCompare(compareString[, locales[, options]])

描述
返回一个数字表示是否 引用字符串 在排序中位于 比较字符串 的前面,后面,或者二者相同。

  • 当 引用字符串 在 比较字符串 前面时返回 -1
  • 当 引用字符串 在 比较字符串 后面时返回 1
  • 相同位置时返回 0

切勿依赖于 -1 或 1 这样特定的返回值。不同浏览器之间(以及不同浏览器版本之间) 返回的正负数的值各有不同,因为W3C规范中只要求返回值是正值和负值,而没有规定具体的值。一些浏览器可能返回-2或2或其他一些负的、正的值。

示例
使用 sort()、localeCompare() 进行中文数组首字母的排序

1
2
3
4
5
function compare(a, b) {
return a.localeCompare(b);
}
resultArr = [ '学习' , '钢材' , '蛋汤' , '房企', '安卓','北京', '藏宝' ] ;
resultArr.sort(compare); // ["安卓", "北京", "藏宝", "蛋汤", "房企", "钢材", "学习"]

我是瘦子

Web Api 相关接口

发表于 2020-09-24 | 阅读次数

HTMLElement

HTMLElement.offsetWidth

引自MDN:是一个只读属性,返回一个元素的布局宽度。一个典型的(译者注:各浏览器的offsetWidth可能有所不同)offsetWidth是测量包含元素的边框(border)、水平线上的内边距(padding)、竖直方向滚动条(scrollbar)(如果存在的话)、以及CSS设置的宽度(width)的值。

语法

1
2
// 返回元素的宽度(包括元素宽度、内边距和边框,不包括外边距)
var offsetWidth = element.offsetWidth;

这个属性将会 round(四舍五入)为一个整数。如果你想要一个fractional(小数)值,请使用 element.getBoundingClientRect()

阅读全文 »
我是瘦子

JavaScript 中 new 一个对象的过程中发生了什么

发表于 2020-09-16 | 阅读次数

我们先创建一个简单的构造函数:

1
2
3
4
5
6
function Rocker(name){
this.name = name;
};
Rocker.prototype.getName = function(){
return this.name;
}

这是最简单不过的构造函数了,正常情况下,我们要生成他的一个实例,只需要:

1
var someOne = new Rocker('Max')

这样就实例化了一个对象,但是,实例化的过程是怎样的呢?

可能很多朋友在网上也看了很多文章,new的过程不就是三步吗?

  1. 开辟一个块内存,创建一个空对象
  2. 执行构造函数,对这个空对象进行构造
  3. 给这个空对象添加proto属性

Or

  1. 创建一个空对象
  2. 把该对象关联到原始对象或者是构造函数
  3. 把新创建的空对象作为原始对象或者构造函数的上下文
  4. 如果原始对象或者构造函数有返回值且为对象,则返回该对象,否则返回新创建的对象

没错,是这三步,但是你真的理解了吗?至少我第一次看挺懵逼的。好吧,最直观的方法就是,把创建一个对象的过程用代码体现出来,这样才能装逼嘛…
体验:让我们创建一个函数,来实现上面new操作符的功能:

1
2
3
4
5
6
7
8
9
10
11
var createObject = function(){
var obj = new Object(), //(1)
Constructor = [].shift.call(arguments); //(2)
obj.__proto__ = Constructor.prototype; //(3)
var ret = Constructor.apply(obj, arguments); //(4)
return typeof ret === 'object' ? ret : obj; //(5)
};
var Freak = createObject(Rocker, 'Freak');
console.log(Freak.name); //Freak
console.log(Freak.getName()); //Freak
console.log(Object.getPrototypeOf(Freak) === Rocker.prototype); //true

就是上面这几句代码,向你展现了一个实例被new出来的过程。

我们来简单分析一下吧,其实很清晰明了了。

在(1)处,我们创建了一个空对象(准确的说是克隆了Object.prototype对象)

接下来(2)取到构造函数,赋值给Constructor变量,也就是说Rocker构造函数变成Constructor的一个引用了

接着(3)把Constructor.prototype(也就是Rocker.prototype)赋值给(1)刚刚创建的obj的原型链,或者这么说,把obj的原型链指向Constructor的原型

(4)我们用apply改变this的指向,用obj代替Constructor构造函数内部的this,并把arguments作为参数传入(在第2步时已经用shift把第一个参数去除了),此时的ret已经是一个合格的实例了!

保险起见,我们(5)返回时判断ret是否是对象,如果不是就返回一个空对象(因为很多人真的不会按照规矩传参!!!)

这时候我们再外部调用这个函数试试,实时证明确实能达到new的效果。

再用getPrototypeOf方法测试一下,Freak的原型链真的指向Rocker的原型!

这就是实例被new出来的过程,你明了吗?

转载:Rockjins Blog

我是瘦子

Js 算法:两数之和

发表于 2020-09-10 | 阅读次数

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

1
2
3
4
给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function (nums, target) {
const _arr = [];
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
_arr.push(i, j);
}
}
}
return _arr;
};

解二:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
let arrIndex = nums.findIndex(v => v === target - nums[i])
if (arrIndex !== -1 && arrIndex !== i) {
return [i, arrIndex]
}
}
}

转载:https://leetcode-cn.com/problems/two-sum

我是瘦子

Js 根据一个多维数组查询最大深度问题

发表于 2020-08-14 | 阅读次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function deep(arr, count = 0, ttt = []) {
for (let index in arr) {
if (Array.isArray(arr[index])) {
count++
deep(arr[index], count, ttt)
} else {
ttt.push(count)
}
}

//return Math.max.apply(null, ttt) + 1
return Math.max(...ttt) + 1;
}

let arr = [1, 2, 3, ['n', 'i', ['t', ['nihao']]], ['a', 'b']]

console.log(deep(arr)) // 4
我是瘦子

Js 数组的深度递归搜索

发表于 2020-08-14 | 阅读次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const fuck = [{"label": "占用道路问题", "value": 31, "children": [{"label": "经营占道", "value": 35, "children": [{"label": "店外经营占道", "value": 40, "children": null }, {"label": "流动摊贩占道", "value": 41, "children": null } ] }, {"label": "垃圾占道", "value": 36, "children": [{"label": "生活垃圾", "value": 42, "children": null }, {"label": "建筑垃圾", "value": 43, "children": null }, {"label": "工业垃圾", "value": 44, "children": null } ] }, {"label": "车辆占道", "value": 37, "children": [{"label": "机动车占道", "value": 45, "children": null }, {"label": "非机动车占道", "value": 46, "children": null } ] }, {"label": "霸占车位", "value": 38, "children": [] }, {"label": "其他占道", "value": 39, "children": [] } ]}, {"label": "“两违”问题", "value": 32, "children": [{"label": "违法建筑", "value": 58, "children": [{"label": "房屋违建", "value": 61, "children": null }, {"label": "小区违建", "value": 62, "children": null }, {"label": "违建棚架", "value": 63, "children": null } ] }, {"label": "违法用地", "value": 59, "children": [] }, {"label": "其他违建", "value": 60, "children": [] } ] }, {"label": "市容设施管理问题", "value": 33, "children": [{"label": "道路损坏", "value": 47, "children": [] }, {"label": "垃圾桶损坏", "value": 48, "children": [] }, {"label": "下水道堵塞", "value": 49, "children": [] }, {"label": "井盖损坏", "value": 50, "children": [] }, {"label": "路灯损坏", "value": 51, "children": [] }, {"label": "树木修剪", "value": 52, "children": [] }, {"label": "水电气", "value": 53, "children": [] }, {"label": "户外广告牌", "value": 54, "children": [] }, {"label": "隔音屏损坏", "value": 55, "children": [] }, {"label": "洒水车问题", "value": 56, "children": [] }, {"label": "其他", "value": 57, "children": [] } ] }, {"label": "其他问题", "value": 34, "children": [] } ]

/**
* 深度递归搜索
* @param {Array} arr 你要搜索的数组
* @param {Function} condition 回调函数,必须返回谓词,判断是否找到了。会传入(item, index, level)三个参数
* @param {String} children 子数组的key
*/
const deepFind = (arr, condition, children) => {
// 即将返回的数组
let main = []

// 用try方案方便直接中止所有递归的程序
try {
// 开始轮询
(function poll(arr, level) {
// 如果传入非数组
if (!Array.isArray(arr)) return

// 遍历数组
for (let i = 0; i < arr.length; i++) {
// 获取当前项
const item = arr[i]

// 先占位预设值
main[level] = item

// 检验是否已经找到了
const isFind = condition && condition(item, i, level) || false

// 如果已经找到了
if (isFind) {
// 直接抛出错误中断所有轮询
throw Error

// 如果存在children,那么深入递归
} else if (children && item[children] && item[children].length) {
poll(item[children], level + 1)

// 如果是最后一个且没有找到值,那么通过修改数组长度来删除当前项
} else if (i === arr.length - 1) {
// 删除占位预设值
main.length = main.length - 1
}
}
})(arr, 0)
// 使用try/catch是为了中止所有轮询中的任务
} catch (err) {}

// 返回最终数组
return main
}

let resultArr = deepFind(fuck, (item, index, level) => item.value === 63, 'children');
console.log(resultArr); // [{…}, {…}, {…}]
console.log(resultArr.map(_ => _.value)); // [32, 58, 63]
阅读全文 »
我是瘦子

关于 ECharts canvas 层级太高 导致 tooltip 被遮盖

发表于 2020-07-08 | 阅读次数
1
2
3
4
/*核心代码*/
canvas {
z-index: -1;
}
我是瘦子

Sequelize 中 Model 的数据类型

发表于 2020-05-27 | 阅读次数

Sequelize 中 Model 的数据类型对应MySQL中的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Sequelize.STRING                      // VARCHAR(255)                  类型:字符串 最大值: 65535个字符
Sequelize.STRING(1234) // VARCHAR(1234) 类型:变长 最大值: 65535个字符
Sequelize.TEXT // TEXT 类型:字符串 最大值:65535个字符
Sequelize.TEXT('tiny') // TINYTEXT 类型:字符串 最大值:255个字符

Sequelize.INTEGER // INTEGER 类型:整型 最大值:范围(-2147483648~2147483647)
Sequelize.BIGINT // BIGINT 类型:整型 最大值:范围(+-9.22*10的18次方)
Sequelize.BIGINT(11) // BIGINT(11) 类型:整型 最大值:范围(+-9.22*10的18次方)

Sequelize.FLOAT // FLOAT 类型:单精度浮点型 8位精度(4字节)
Sequelize.FLOAT(11) // FLOAT(11) 类型:单精度浮点型 8位精度(4字节)
Sequelize.FLOAT(11, 12) // FLOAT(11,12) 类型:精度浮点型 8位精度(4字节) m总个数,d小数位


Sequelize.DOUBLE // DOUBLE 类型:双精度浮点型 16位精度(8字节)
Sequelize.DOUBLE(11) // DOUBLE(11) 类型:双精度浮点型 16位精度(8字节)
Sequelize.DOUBLE(11, 12) // DOUBLE(11,12) 类型:双精度浮点型 16位精度(8字节) m总个数,d小数位

Sequelize.DECIMAL // DECIMAL 类型:定点数型
Sequelize.DECIMAL(10, 2) // DECIMAL(10,2) 类型:定点数型 参数m<65 是总个数,d<30且 d<m 是小数位

Sequelize.DATE // DATETIME 类型:日期时间类型 范例:'2009-05-12 02:31:44'
Sequelize.DATE(6) // DATETIME(6)
Sequelize.DATEONLY // DATE without time.
Sequelize.BOOLEAN // TINYINT(1) 类型:整型 范围(-128~127)

Sequelize.ENUM('value 1', 'value 2') // ENUM 类型:枚举

Sequelize.BLOB // BLOB 类型:二进制数据
Sequelize.BLOB('tiny') // TINYBLOB 类型:二进制数据
12…4
I am a thin man

I am a thin man

那些玩笑话中,总掺杂着真心话。

33 日志
23 标签
RSS
© 2016 - 2020 I am a thin man
由 Hexo 强力驱动
主题 - NexT.Pisces
本站访客数人次 本站总访问量次