(本周总结)工具库源码+算法+原生
202快乐数
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1
如果可以变为1,那么这个数就是快乐数
输入: 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
/*和不等于1,且重复就不是快乐树*/
const isHappy = n => {
let set = new Set()
n += ''
let sum = 0
while (sum != 1) {
sum = 0
for (let i = 0; i < n.length; i++) {
sum += n[i] ** 2
}
if (set.has(sum)) return false
n=sum+''
set.add(sum)
}
return true
}
console.log(isHappy(20))//false
//第二种
const isHappy = n => {
let exit = []
let sum
while (n != 1) {
sum = 0
while (n !=0) {
sum += (n % 10) ** 2
n = parseInt(String(n / 10))
}
if (exit.indexOf(sum) > -1) {
return false
}else{
exit.push(sum)
}
n=sum
}
return true
}
Leetcode 1137 第 N 个泰波那契数
输入:n = 4
输出:4
T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2
给你整数 n,请返回第 n 个泰波那契数 Tn 的值。
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4
const Solution = n => {
const arr = [0, 1, 1]
if (n < 3) {
return arr[n]
}
return Solution(n - 3) + Solution(n - 2) + Solution(n - 1)
}
console.log(Solution(5))
const Solution = n => {
const arr = [0, 1, 1]
if (n < 3) {
return arr[n]
}
for (let i = 3; i <= n; i++) {
arr[i] = arr[i - 3] + arr[i - 2] + arr[i - 1]
}
return arr[n]
}
console.log(Solution(5))
LeetCode 179 数组拼接为最大数
输入: [10,2]
输出: 210
输入: [3,30,34,5,9]
输出: 9534330
const largesNumber = nums => {
nums = nums.map(String)
nums.sort((a, b) => parseInt(b + a) - parseInt(a + b))
if(nums[0]==0) return '0'
return nums.join('')
}
LeetCode 200
const numIslands = nums => {
if (nums.length == 0) return 0;
let count = 0;
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < nums[0].length; j++) {
if (nums[i][j] == 1) {
count++
helper(i, j, nums)
}
}
}
return count
}
const helper = (i, j, nums) => {
if (i < 0 || j < 0 || i >= nums.length || j >= nums[0].length || nums[i][j] != 1) return ;
nums[i][j] = '*';
helper(i - 1, j, nums);
helper(i + 1, j, nums);
helper(i, j - 1, nums);
helper(i, j + 1, nums)
}
console.log(numIslands([['1', '0', '1', '1', '1'], ['1', '0', '1', '0', '1'], ['1', '1', '1', '0', '1']]))
198 打家劫舍
相邻两家不能同时闯入
输入: [1,2,3,1] 输出: 4 1 + 3 = 4 输入: [2,7,9,3,1] 输出: 12 2 + 9 + 1 = 12
const rob1 = nums => {
let a = 0,
b = 0;
for (let i = 0; i < nums.length; i++) {
if (i % 2 == 0) {
//a += nums[i];
// a = Math.max(b, a)
a = Math.max(b, (a + nums[i]))
} else {
// b+=nums[i]
// b=Math.max(a,b)
b = Math.max(a, (b + nums[i]))
}
}
return Math.max(a, b)
}
///动态规划
let n = nums.length;
if (n <= 1) return n == 0 ? 0 : nums[0];
let arr = [];
arr[0] = nums[0];
arr[1] = nums[1]
for (let i = 2; i < n; i++) {
arr[i] = Math.max(arr[i - 1], nums[i] + arr[i - 2]);
}
console.log(arr)
return arr[n - 1]
}
leetCode 191 位1的个数
const hammingh = n => n.toString(2)
.split('')
.reduce((acc, val) => (val == '1' && acc++, acc), 0)
leetCode 190 颠倒二进制位
var reverseBits = n => {
let t = n.toString(2).split('')
while (t.length < 32) {
t.unshift('0')
}
return parseInt(t.reverse().join(''),2)
};
console.log(reverseBits(100))
leetCode 49
输入: ['abc','acb','bbc','cbb']
输出: [['abc','acb'],['bbc','cbb']]
const GroupAnrgrams = strs => { let map = new Map(); for (let i = 0; i < strs.length; i++) { let key=strs[i].split('').sort().join(); if (!map.has(key)) { map.set(key,[strs[i]]) }else{ let temp=map.get(key) temp.push(strs[i]) map.set(key,temp) } } return Array.from(map.values()) } console.log(GroupAnrgrams(['abc', 'bcd', 'mss','bca']))
leetCode 5 最长回文子串
输入: "babad"
输出: "bab"
const Solution = str => { let n = str.length; let res = '' const helper = (i, j) => { //查找回文的中心 while (i >= 0 && j < n && str[i] == str[j]) { i -= 1 j += 1 } //确定好边界 if (res.length < j - i - 1) { res = str.slice(i + 1, j) } } for (let i = 0; i < n; i++) { helper(i,i) helper(i,i+1) } return res } console.log(Solution('abcbaddd')) //第二种 //这种for循环看得少 for (let i = 0; i < n; i++) { for (let j = i; j >= 0; j--) {}} n=3 //输出的结果 [ [ 0, 0 ], [ 1, 1 ], [ 1, 0 ], [ 2, 2 ], [ 2, 1 ], [ 2, 0 ], [ 3, 3 ], [ 3, 2 ], [ 3, 1 ], [ 3, 0 ] ] 不好理解,我就不写啦
164. 最大间距
给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。
例如
输入: [3,6,9,1]
输出: 3
const maxinum = nums => { let n = nums.length; let res = 0; if (n < 2) { return 0 } nums.sort((a,b)=>a-b) for (let i = 1; i < n; i++) { res = Math.max(res, nums[i] - nums[i - 1]) } return res }
DOM复习
document.querySelector
返回第一个匹配的Element
document.querySelectorAll
返回的是一个类数组Array.from(document.querySelectorAll('.aaa')) .forEach(val => val.innerHTML = '333'); [...document.querySelectorAll('.aaa')].map(val=>val.innerHTML='333')
但是上面的这两种性能较差,尽量使用
document.getElementById() document.getElementsByTagName()
属性查找
document.querySelector("div[class='bbb']")
后代查找
$el.querySelector('.bbb')
兄弟元素
let a=document.querySelector('.bbb') //我的父节点的所有孩子,除掉自身的所有兄弟节点 let b=[...a.parentNode.children].filter(val=>val!==a)
上一个元素
el.previousElementSibling;
下一个元素
el.nextElementSibling;
Input/Textarea
document.querySelector('.aaa').value
event
在vue中是在点击或者其实事件传入$event 原生事件委托 let a=document.querySelector('.aaa') a.addEventListener('click',(e)=>{ console.log(e.target) //拿到点击的dom节点 })
获取属性
el.getAttribute('class')
设置属性
el.setAttribute('属性','值')
添加class
$el.classList.add('aaaa')
删除class
$el.classList.remove('aaa')
has class
$el.classList.contains('aaa')
toggle class
$el.classList.toggle('aaa')
offset 偏移
offsetWidth和offsetHight 获取节点的宽度和高度
offset宽/高 = 盒子自身的宽/高 + padding+border; `offsetWidth` =width+padding+border; `offsetHeight` =Height+padding+border;
offsetLeft和offsetTop (检测距离父盒子有定位的左/上面的距离)
offsetParent (检测父系盒子中带有定位的父盒子节点)
区别
offsetTop返回的是只读的,且返回的是数字
scroll
scrollTop scrollLeft
Rambda工具库源码学习
curry() 这个很经典放前面
curry((a,b,c)=>a+b+c)(1,2,3) //6
curry((a,b,c)=>a+b+c)(1)(2)(3) //6
const curry = (fn, args = []) =>
(..._args) => (rest => rest.length >= fn.length ? fn(...rest) : curry(fn, rest))([...args, ..._args])
const curry = (fn, ...args) =>
fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args);
好懂版
const curry = (fn, ...args) => (..._args) => (test => test.length < fn.length ? curry(fn, ...test) : fn(...test))([...args, ..._args])
const curry = (fn, ...args) => {
if (args.length<fn.length) {
return curry.bind(null, fn, ...args)
}
return fn(...args)
}
add()
add(1,2) //3
add(1)(2) //3
function add(a, b) {
if (arguments.length == 1) {
return _=>add(a,_)
}
return a+b;
}
adjust()
adjust(val=>val+1,1,[1,2,3])// [1,3,3]
const adjustRaw = (fn, idx, list) => {
const clone = list.slice()
const Index = list.length > 0 ? idx : list.length - idx;
clone[Index] = fn(clone[Index])
return clone
}
all()
all(v => v > -1, [1, 1, 1, 1, -1])// false
all(val=>val==2)([2, 2, 2, 2,]) //true
function all(fn, list) {
if (arguments.length == 1) return _ => all(fn, _)
return list.every(fn)
}
allPass
const input = {
a: 1,
b: 2,
}
const rules = [
x => x.a === 1,
x => x.b === 2,
]
allPass(rules, input) //true
allPass(rules)(input)//true
function allPass(fnArray, obj) {
if (arguments.length == 1) return _ => allPass(fnArray, _);
return fnArray.some(fn => fn(obj))
}
always
const always = val => () => val
always(3)() //3
defaultTo
如果第二个参数不是
null
、undefined
或NaN
,则返回第二个参数,否则返回第一个参数(默认值)
defaultTo(300)(undefined/null/NaN) //300 defaultTo(300)(30) //30 defaultTo(300,undefined,null,3) //30 const flag = s => s == undefined || Object.is(s, NaN) function defaultTo(a, ...b) { if (arguments.length == 1) { return _ => defaultTo(a, _) } if (arguments.length == 2) { return flag(b[0]) ? a : b[0] } let i = 0; while (i < b.length) { if (!flag(b[i])) { return b[i] } i++ } return a }
dissoc()
dissoc('b', {a: 1, b: 2, c: 3}); //=> {a: 1, c: 3}
function dissoc(prop, obj) {
if (arguments.length == 1) {
return _ => dissoc(prop, _)
}
if (obj == undefined || obj == null) {
return {}
}
let a = Object.assign({}, obj)
delete a[prop]
return a
}
equals
const type = val => {
if (typeof val == 'number') {
return isNaN(val) ? 'NaN' : 'number'
} else {
return Object.prototype.toString.call(val)
.split(' ')[1].slice(0, -1)
}
}
function equals(a, b) {
if (arguments.length == 1) {
return _ => equals(a, _)
}
if (a === b) {
return true
}
if (type(a) !== type(b)) {
return false
}
if (type(a) == 'Array') {
let aArray = a.concat()
let bArray = b.concat()
if (aArray.toString() !== bArray.toString()) {
return false
}
let flag = true;
aArray.forEach((val, index) => {
if (flag) {
if (val != bArray[index] && !equals(val, bArray[index])) {
flag = false
}
}
})
return flag;
}
if (type(a) == 'Object') {
const aKeys = Object.keys(a)
if (aKeys.length !== Object.keys(b).length) {
return false
}
let flag = true;
aKeys.map(val => {
if (flag) {
const aValue = a[val];
const bValue = b[val];
if (aValue !== bValue && !equals(aValue, bValue)) {
flag = false
}
}
})
return flag
}
return false
}
lodash源码深入
after()
调用多少次后才执行
const after = (n, func) => { return (...args) => { if (--n < 1) { return func.apply(null, args) } } } **例子** let f = after(2, (a, b) => { return a + b }) console.log(f(2, 3)) //undefined console.log(f(2, 3)) //5
before(n,func)
调用不超过n次
const before = (n, func) => { return (...args) => { if (n-- > 0) { return func.apply(null, args) } func=undefined } } let a=before(2,(a,b)=>a+b) console.log(a(1, 2)) //3 console.log(a(1, 2)) //3 console.log(a(1, 2)) //undefined
sum(array)
const sums = array => { let result = 0; if (array != null && array.length) { for (let item of array) { result += item } } return result }
pull(array,...args)
**例子** let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ] const pull = (arr, ...args) => { let pulled = arr.filter(val => !args.includes(val)) //删除原有数组的元素 arr.length = 0 pulled.forEach(val => arr.push(val)) }; let arr = [1, 2, 3, 4, 5] pull(arr, 1, 2) console.log(arr)
uuid(a,b)
UUID 是 通用唯一识别码
function uuid(a, b) {
for (
b = a = ''; a++ < 36;
b += a * 51 & 52 ?
(a ^ 15 ? 8 ^ Math.random() * (a ^ 20 ? 16 : 4) : 4).toString(16)
: '-') ;
return b
}
console.log(uuid(2, 3))
//4f656637-ea34-4a16-a4b0-31872ab177da
这种位运算我这种级别还看不懂,先写上去
deepClone()
const deepClone = obj => {
let clone = Object.assign({}, obj)
Object.keys(clone)
.forEach(val => {
clone[val] = typeof obj[val] == 'object' ? deepClone(obj[val]) : obj[val]
})
if (Array.isArray(obj) && obj.length) {
return (clone.length = obj.length) && Array.from(clone)
} else {
return Array.isArray(obj) ? Array.from(obj) : clone
}
}
mb()
//要查找的对象
var obj1 = {
a: {
b: [{ hello: 'world' }]
}
};
//要查找的条件
const arr = ['a', 'b', 0, 'hello']
console.log(a(arr)(obj1))
//world
const mb=p=>obj=>p.map(val=>obj=(obj||{})[val])&&obj
qart
给二维码添加背景
自执行函数
void function() {
console.log(0)
}()
+function(){
console.log(1)
}()
-function(){
console.log(2)
}()
~function(){
console.log(3)
}();
!function(){
console.log(4)
}();
(function(){
console.log(5)
})()
对象成员
const obj={
name:'zhangsan',
age:12,
method(){
return 2
}
}
for (let item in obj) {
console.log(item) //打印键
}
使用对象成员的`.` `[]`
"." 和"[]" 都是对象成员存取运算符,所不同的是:
前面右边的运算元必须是一个标识符,后面中间的运算元可以是变量,直接量或表达式
obj.name
obj['name']
obj.method()
obj.['method']()
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬