Button
button{
100px;
height: 50px;
border-radius:25px;
color:#000;
border:2px solid blue;
background-color: transparent;
}
overflow:scroll
出现滚动条
记忆函数
const add = () => {
let a = {}
return num => {
const result=num+10
a[num]=result
console.log(a)
if (num in a) {
return a[num]
}else{
return result
}
}
}
let a = add()
console.log(a(20))
console.log(a(10))
import 和require
import 命令是编译阶段执行的,在代码运行之前,就是意味着被导入的模块会先运行,而导入模块的文件会后运行
require() 运行代码时候再运行
BigInt(新的基础类型)
BigInt
数据类型的目的是比Number
属性类型支持的范围更大的整数值,主要用于大于Number
数据类型支持的范围要创建
BigInt
,只需在整数的尾数追加n即可或者
BigInt("9007199254740995")
9007199254740995n
console.log(typeof 10n); // → bigint 10n==10 //true 与`BigInt`操作数一起使用时,算术运算符应该返回`BigInt` 值,因此,除法运算符的结果会自动向下舍入到最接近的整数 25n/10n; // 2n 不能对混合使用`number`和`BigInt` 操作数执行算术操作 可以通过转化进行操作 BigInt(10)+10n 10+Number(10)
VDOM
VDOM就是一个数据结构
从逻辑上vdom就是用来抽象DOM的,底层上vdom普遍实现是基于哈希表这种数据结构
{ type:'div', props:{ name:'lucifer' }, children:[{ type:'span', props:{}, children:[] }] }
所以我们从面向DOM编程,切换到面向VDOM编程,由于VDOM又是由数据驱动的,所以也就是数据驱动
DOM dif算法
AST
AST(抽象语法树) 是前端编译(转义)的理论基础
AST厉害就厉害在它本身不涉及到任何语法,因此你只要编写相应的转义规则,就可以将任何语法转义到任何语法,这就是babel,PostCSS,prettier,typescript
等的原理,除此之外,还有很多应用场景,比如编辑器
Lodash源码分析
_.chunk (不怎么理解)
_.chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]
console.log([1, 2, 3, 4].reduce((acc, val, i) => {
return [...acc,[val]]
},[]))
//[[1],[2],[3],[4]]
i%2
输入: 0 1 2 3 4
输出: 0 1 0 1 0
const chunk = (arr, size) => {
return arr.reduce((acc, val, index) => {
if (index % size === 0) {
return [...acc, [val]]
} else {
//[[1,2],[3,4],[5]]
return [...acc.slice(0, -1), [...acc.slice(-1)[0], val]]
//[[1,2],[3,4],[5,6]]
}
}, [])
}
console.log(chunk([0,1,2,3,4,5,6], 2));
//[ [ 0, 1 ], [ 2, 3 ], [ 4, 5 ], [ 6 ] ]
找到二维数组中不同的数
let arrays = [[1, 2, 3, 4, 5], [5, 2, 10]];
console.log(arrays.reduce((a, b) => a.filter(c => !b.includes(c))));
//a=>[1,2,3,4,5]
//b=>[5,2,10]
console.log([[1, 2, 3, 4, 5], [1, 2, 4]]
.reduce((acc, val) => {
//return val //[1,2,4]
return acc //[1,2,3,4,5]
}))
// output: [1, 3, 4]
深度降维
const flattenDeep = (arr) => Array.isArray(arr)
? arr.reduce( (a, b) => a.concat(flattenDeep(b)) , [])
: [arr]
求多维数组的交集
let arrays = [[1, 2, 3,10], [101, 1, 10], [2, 1,10]];
console.log(arrays.reduce((acc, val) => acc.filter(item => val.includes(item))))
根据数组的个数,排成一个对象
console.log(['one', 'two', 'three'].reduce((acc, val, index, array, k = val.length) => {
(acc[k] || (acc[k] = [])).push(val)
return acc
}, {}))
//{ '3': [ 'one', 'two' ], '5': [ 'three' ] }
函数式编程
函数式编程中的函数指的是数学中的函数,而不是javascript中的函数
纯函数就是给定输入,输出总是相同的函数
柯里化 const add=x=>y=>x+y add(1)(2) //3 const g = x => x + 20 const f = x => x * 2 const compose = (f, g) => x => f(g(x)) console.log(compose(f, g)(10)) //40 **bind** const add = (x, y, z) => x + y + z const plus = add.bind(null, 10) console.log(plus(10, 10))//30 console.log(plus(20, 20))//50 //[1, 2, 3] => { 1: 1, 2: 4, 3: 9 } const mapObject = (arr, fn) => { let itemArr = arr.map(fn); return arr.reduce((acc, val, index) => (acc[val] = itemArr[index], acc), {}) } //求最小值,最大值 const over=(...fns)=>(...args)=>fns.map(val=>val.apply(null,args)) over(Math.min, Math.max)(1, 2, 3, 4) //输入(9,3) 输出 [81,6] 也就是第一个参数**2 第二个参数*2 //简单版 const over1 = (first, last) => [first ** 2, last * 2] console.log(over1(9, 3))//[81,6] //封装版 const overArg=(fn,fns)=>(...args)=>args.map((val,i)=>fns[i](val)) console.log(overArg( [x => x ** 2, x => x * 2])(4,6)) //[ 16, 12 ] //高阶函数 //自执行函数 (function (s) { return s*2 })(2);//4 (x => x * 2)(2);//4 //高阶 const add=fn=>x=>fn(x); add(x => x + 2)(2)//4
隔行变色
li:nth-child(2n) {
background-color: red;
}
li:nth-of-type(2n-1) {
background-color: gold;
}
超过一行省略号...
.aaa{
200px;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
伪元素
.aaa{
position:relative;
}
.aaa:after{
content:'';
position:absolute;
right:0;
bottom:0;
}
undefined
未为变量赋值时默认值为undefined
当访问未初始化的变量,不存在的对象属性,不存在的数组元素等时,将接收一个undefined
的值
1138
U
上
D
下
L
左
R
右
!
几个输入:target = "leet" 输出:"DDR!UURRR!!DDD!" 输入:target = "code" 输出:"RR!DDRR!UUL!R!" const alphabet = target => { let res = ''; let x = 0, y = 0; for (let item of target) { let x1 = Math.floor((item.charCodeAt() - 97) / 5), y1 = (item.charCodeAt() - 97) % 5; //当前的位置l x轴的位置 c是y轴的位置 let l = x1 - x; c = y1 - y; //记得x轴=>c y轴=>l /*上*/ if (l < 0) { for (let i = 0; i < -l; i++) { res += 'U' } } /*下*/ if (l > 0) { for (let i = 0; i < l; i++) { res += 'D' } } /*左*/ if (c < 0) { for (let i = 0; i < -c; i++) { res += 'L' } } /*右*/ if (c > 0) { for (let i = 0; i < c; i++) { res += 'R' } } res += '!'; x = x1, y = y1; } return res } console.log(alphabet('kb'))
LeetCode1128
求多米诺骨牌的数量
dominoes[i] = [a, b] 和 dominoes[j] = [c, d]
等价的前提是 ac 且 bd,或是 ad 且 bc
也就是[1,2],[2,1]或者是[1,2],[1,2]
例如
输入[[1, 2], [2, 1], [3, 4], [3, 4],[6,5], [5, 6]]
输出 3
var numEquivDominoPairs = function (dominoes) { let arr = Array.from({ length: 100 }, v => 0); let res = 0; for (let item of dominoes) { //*10,是为了 [2,5]或者[3,4]不是相等的 res += arr[Math.min(item[0], item[1])*10 + Math.max(item[0], item[1])]++ } return res; }; console.log(numEquivDominoPairs([[1, 2], [2, 1], [3, 4],[2,5],[6,5], [5, 6]])) //3
724寻找数组的中心索引
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
左边的和等于右边的和 简化为: 总和-右边的和-中间数=左边的和 const Solution = nums => { let sum = 0; leftSum = 0; sum = nums.reduce((acc, val) => acc + val) for (let i = 0; i < nums.length; i++) { if (leftSum == sum - leftSum - nums[i]) { return i; } leftSum += nums[i] } return -1 } console.log(Solution([1,2,3,6,2,3,1]))
747 至少是其他数字两倍的最大数
在一个给定的数组
nums
中,总是存在一个最大元素 。查找数组中最大元素是否至少是数组中每个其他数字的两倍
如果是,返回最大的索引,否则返回-1
实例1
输入:nums=[3,6,1,0]
输出:1
思路:6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1
实例2
输入: nums = [1, 2, 3, 4]
输出: -1
解释: 4没有超过3的两倍大, 所以我们返回 -1.找到最大和第二大的元素,看最大的是不是第二大的2倍,若不是直接返回-1,在数组中找到索引 const Solution = nums => { if (nums.length == 1) { return 0 } //最大值 let max = 0; //第二大的值 let second = 0; //索引 let index = 0; for (let i = 0; i < nums.length; i++) { if (max < nums[i]) { max = nums[i] index = i; } } for (let item of nums) { if (item < max && second < item) { second = item } } console.log(max, second) if (second * 2 <= max) { return index } return -1 } console.log(Solution([1, 2, 3, 4, 9]))
283 移动零
把一个数组里所有的0都移到后面,不能改变非零数的相对位置关系,而且不能拷贝额外的数组。
举例
输入:[0,1,0,3,5,0]
输出:[1,3,5,0,0,0]
//双指针 const Solution = nums => { let index = 0; for (let i = 0; i < nums.length; i++) { if (nums[i] != 0) { nums[index++] = nums[i] } } while (index < nums.length) { nums[index++] = 0; } return nums } console.log(Solution([0, 1, 1, 2, 3, 0, 0, 21])) //[ 1, 1, 2, 3, 21, 0, 0, 0 ]
LeetCode 389找不同
输入:
s = "abcd"
t = "abcde"输出:
'e'
运算性质: A^B^B=A //第一种位运算 const findThe = (s, t) => { let t1 = 0 let index = 0; while (index < s.length) { t1 ^= s.charCodeAt(index) index++ } let b = 0; while (b < t.length) { t1 ^= t.charCodeAt(b) b++ } return String.fromCharCode(t1) } console.log(findThe('abc', 'bc')) //'a' //桶排序 const findThe = (s, t) => { const ans = Array.from({ length: 26 }, v => 0) let i = 0, j = 0, k = 0; while (i < s.length) { ans[s.charCodeAt(i) - 97]++ i++ } while (j < t.length) { ans[t.charCodeAt(j) - 97]++ j++ } while (k < ans.length) { if (ans[k] == 1) { return String.fromCharCode(k + 97) } k++ } return -1 }
leetCode 455分发饼干
你的目标是尽可能满足越多数量的孩子,并输出这个最大数值
实例一
输入:[1,2,3],[1,1]
输出:1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。实例二
输入: [1,2], [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.const findCount = (g, s) => { g.sort() s.sort() let i = 0, j = 0; while (i < g.length && j < s.length) { //满足就是s[j]>=g[i] //如果满足,饼干j++,结束判断后换个孩子(i++) if (s[j] >= g[i]) { j++ } i++ } return i } console.log(findCount([1, 2], [1,2,3])) //满足2个孩子
48 旋转矩阵
/* * Given input matrix = [ [1,2,3], [4,5,6], [7,8,9] ], rotate the input matrix in-place such that it becomes: [ [7,4,1], [8,5,2], [9,6,3] ] */ const rotate = (matrix) => { let arr = Array.from({ length: matrix.length }, v => []) for (let i = 0; i < matrix.length; i++) { for (let j = 0; j < matrix[i].length; j++) { arr[i][j]=matrix[matrix.length-1-j][i] } } return arr } let array1=[ [1,2,3], [4,5,6], [7,8,9] ]; console.log(rotate(array1))
136 只出现一次的数
[1, 2, 3, 1, 1, 10, 2].filter(
(val, index, array) =>
array.indexOf(val) == array.lastIndexOf(val))
// 5^5=0 0^5=5
var singleNumber = function (nums) {
let result=0;
for (let i = 0; i < nums.length; i++) {
result^=nums[i]
}
return result
};
const singleNumber = function (nums) {
let set = new Set();
for (let i = 0; i < nums.length; i++) {
if (set.has(nums[i])) {
set.delete(nums[i])
} else {
set.add(nums[i])
}
}
return Array.from(set)
};
//2*(去重的数组的和)-原数组的和
//只考虑重复一次
const singleNumber = function (nums) {
let set = new Set(nums);
return Array.from(set).reduce((acc,val)=>acc+val)*2-nums.reduce((acc,val)=>acc+val)
};
console.log(singleNumber([1, 2, 4,1,2]))
79单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] 给定 word = "ABCCED", 返回 true. 给定 word = "SEE", 返回 true. 给定 word = "ABCB", 返回 false. [ ['A', 'B', 'C'], ['D', 'A', 'A'], ['G', 'C', 'D'] ] 'ABCAD' // 要走的数组,给定的路径数组 //原路径,新路径 const exist = (thePath, newPath) => { for (let y = 0; y < thePath.length; y++) { for (let x = 0; x < thePath[0].length; x++) { //d是走了几步 if (finds(thePath, newPath, y, x, d=0)) { return true } } } return false } const finds = (thePath, newPath, y, x, d) => { //走的长度等于要走的数组的长度 if (d == newPath.length) return true; //x,y不能大于数据的长度,也不能少于0 if (y < 0 || x < 0 || y == thePath.length || x == thePath.length) return fasle; //开始比较 if (thePath[y][x] != newPath[d]) return false; //记录走过上一步的位置 let temp = thePath[y][x] thePath[y][x]='*' //是否可以走下一步 /*右*/ let exist = finds(thePath, newPath, y, x + 1, d + 1) /*左*/ || finds(thePath, newPath, y, x - 1, d + 1) /*下*/ || finds(thePath, newPath, y + 1, x, d + 1) /*上*/ || finds(thePath, newPath, y - 1, x, d + 1) //移动到上一步走的位置 thePath[y][x]=temp return exist } console.log(exist([['A', 'B', 'C'], ['D', 'A', 'A'], ['G', 'C', 'D']], 'ABC'))
41 缺失的第一个正数
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0] 输出: 3
示例 2:
输入: [3,4,-1,1] 输出: 2
示例 3:
输入: [7,8,9,11,12] 输出: 1
const Solution=nums=>{ let i=1; while (i) { if (nums.indexOf(i) < 0) { return i } i++ } } var firstMissingPositive = function (nums) { let set = new Set(); for (let i = 0; i < nums.length; i++) { //nums[i]>=1 且 每个数小于数组的个数 if (nums[i] >= 1 && nums[i] <= nums.length) { set.add(nums[i]) } } for (let i = 1; i <= nums.length; i++) { if (!set.has(i)) { return i } } return nums.length + 1 }; console.log(firstMissingPositive([3, 4, -1, 1]))