html+css
元素水平垂直居中
<div class="item-1">
<div class="item-2"></div>
</div>
// 1
.item-1 {
width: 100px;
height:100px;
background-color: pink;
position: relative;
}
.item-2 {
width: 50px;
height: 50px;
background-color: aqua;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
// 2
.item-1 {
width: 100px;
height:100px;
background-color: pink;
position: relative;
}
.item-2 {
width: 50px;
height: 50px;
background-color: aqua;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
// 3
.item-1 {
width: 100px;
height:100px;
background-color: pink;
display: flex;
align-items: center;
justify-content: center;
}
js
promise
const PENDING = 'PENDING';
const FUFILLED = 'FUFILLED';
const REJECTED = 'REJECTED';
function resolvePromise(promise, x, resolve, reject) {
if (x === promise) {
throw new Error('错误');
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
// x 有可能是promise
let called = false;
try {
let then = x.then;
if (typeof then === 'function') {
// 认定是promise
then.call(
x,
(y) => {
if (called) return;
called = true;
// 防止y 还是一个promise
resolvePromise(promise, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.reason = null;
this.onResolvedCallback = [];
this.onRejectedCallback = [];
const resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (this.status === PENDING) {
this.status = FUFILLED;
this.value = value;
this.onResolvedCallback.forEach((fn) => {
fn();
});
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallback.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
onRejected =
typeof onRejected === 'function'
? onRejected
: (err) => {
throw err;
};
// promise 的链式调用要求返回一个promise
let promise = new Promise((resolve, reject) => {
if (this.status === PENDING) {
this.onResolvedCallback.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallback.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === FUFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
});
return promise;
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
static reject(value) {
return new Promise((resolve, reject) => {
reject(value);
});
}
// all 有一个失败就停止,全部成功才是成功, 有一个失败了,就报错了
static all(promises) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
const processSuccess = (index, val) => {
result[index] = val;
if (++times === promises.length) {
resolve(result);
}
};
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
if (p && typeof p.then === 'function') {
p.then((data) => {
processSuccess(i, data);
}, reject);
} else {
processSuccess(i, p);
}
}
});
}
// 有一个成功或失败了,就停止,返回不是数组
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
if (p && typeof p.then === 'function') {
p.then(resolve, reject);
} else {
resolve(p);
}
}
});
}
// 不管失败还是成功都能得到所有的结果
static allSettled(promises) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
const process = (index, val) => {
result[index] = val;
if (++times === promises.length) {
resolve(result);
}
};
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
if (p && typeof p.then === 'function') {
p.then(
(data) => {
process(i, {
status: p.status,
value: data
});
},
(e) => {
process(i, {
status: p.status,
reason: e
});
}
);
} else {
process(i, p);
}
}
});
}
// 有一个成功了就走成功,都失败了,才会走失败
static any(promises) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
const process = (index, val) => {
result[index] = val;
if (++times === promises.length) {
resolve(result[result.length - 1]);
}
};
for (let i = 0; i < promises.length; i++) {
let p = promises[i];
if (p && typeof p.then === 'function') {
p.then(
(data) => {
resolve(data);
},
(e) => {
process(i, e);
}
);
} else {
process(i, p);
}
}
});
}
}
export default Promise;
promise 的缺点
1、状态不可追踪 2、函数一旦触发,不能取消 3、函数的状态必须靠resolve,reject才能获取
函数状态悬而为未绝的时候,需要设定超时来控制函数返出
柯里化
function curry(fn, ...args) {
if (args.length < fn.length) {
return (...innerArgs) => curry(fn, ...args, ...innerArgs);
} else {
return fn(...args);
}
}
function _add(a, b, c, d, e) {
return a + b + c + d + e;
}
const add = curry(_add);
console.log(add(1));
console.log(add(1, 2, 3, 4, 5));
// console.log(add(1, 2)(3)(4)(5));
数组手写方法
let arr = [ 1, 2, 3, 4, 5, 6, 7 ];
let arr1 = [ 1, 1, 1, 1, 1 ];
Array.prototype.wyMap = function(callback, thisArgs) {
let res = [];
let arr = this;
const ctx = thisArgs ? thisArgs : arr;
for (let i = 0; i < arr.length; i++) {
res.push(callback.call(ctx, arr[i], i));
}
return res;
};
let wymap = arr.wyMap(
function(item, index) {
return item + 1;
},
[ 1, 2, 3 ]
);
let eachRes = [];
let wyEach = arr.forEach((item) => {
eachRes.push(item * 2);
});
console.log(eachRes);
Array.prototype.wySome = function(callback) {};
Array.prototype.wyfilter = function(callback, thisArg) {
let res = [];
let arr = this;
for (let i = 0; i < arr.length; i++) {
let current = callback(thisArg, arr[i]);
if (current) {
res.push(arr[i]);
}
}
return res;
};
let wyfilter = arr.wyfilter((item) => {
return item % 2 === 0;
});
Array.prototype.wyReduce = function(callback, sum) {
let list = this;
let res = undefined;
if (sum === undefined) {
res = list[0];
} else {
res = sum;
}
for (let i = sum === undefined ? 1 : 0; i < list.length; i++) {
res = callback(res, list[i], i, list);
}
return res;
};
arr.wyReduce((pre, current, index, list) => {}, 0);
let obj1 = {
name: 'wy',
foo: {
age: 10,
arr: [ 1, 2, 3 ]
}
};
function clone(obj, map = new Map()) {
let res = {};
for (let key in obj) {
if (typeof obj[key] !== 'object') {
res[key] = obj[key];
} else {
if (map.get(key)) {
res[key] = map.get(key);
}
map.set(key, obj[key]);
res[key] = clone(obj[key], map);
}
}
return res;
}
let obj2 = clone(obj1);
obj2.name = 'ee';
obj2.foo.age = 30;
obj2.foo.arr[0] = 6;
function _add(a, b, c, d) {
return a + b + c + d;
}
function curry(fn, ...args) {
if (args.length < fn.length) {
return (...curryArgs) => curry(fn, ...args, ...curryArgs);
} else {
return fn(...args);
}
}
let add = curry(_add);
let sum = add(1, 2, 3, 4);
let sum1 = add(1)(2)(3)(4);
// console.log(sum1);
/**
* instanceOf
*/
function wyIntanceOf(left, right) {
let proto = left.__proto__;
while (true) {
if (proto === right.prototype) return true;
proto = proto.__proto__;
}
return false;
}
function Person() {
this.name = 'wy';
}
let person = new Person();
// console.log(wyIntanceOf(person, Person));
call-apply-bind
let obj = {
name: '章三'
};
function getName(age, address) {
console.log('this.name', this.name, age, address);
}
Function.prototype.wyCall = function(content, ...args) {
content.$fn = this;
content.$fn(...args);
delete content.$fn;
};
Function.prototype.wyApply = function(content, args) {
content.$fn = this;
content.$fn(...args);
delete content.$fn;
};
Function.prototype.wyBind = function(content, ...args) {
content = Object(content);
const _this = this;
return function(...fnArgs) {
content.$fn = _this;
content.$fn(...[ ...args, ...fnArgs ]);
delete content.$fn;
};
};
getName.wyCall(obj, 10, '北京');
getName.wyApply(obj, [ 10, '北京' ]);
const bindName = getName.wyBind(obj, 10);
bindName('上海');
clone
/**
* 对象拷贝
*/
let obj = {
name: '张三',
info: {
like: 'eee',
age: 20
}
};
obj.obj = obj
function cloneHandle(source, target, map) {
if (map.get(source)) {
return map.get(source)
}
map.set(source, target)
for(let key in source) {
target[key] = clone(source[key], map)
}
return target
}
function clone(source, map = new Map()) {
let target = {}
let type = Object.prototype.toString.call(source).toLowerCase();
if (type === '[object object]') {
target = {}
return cloneHandle(source, target, map)
} else if (type === '[object array]') {
target = []
return cloneHandle(source, target, map)
} else {
return source
}
}
// function clone(source) {
// if (typeof source === 'object') {
// let target = Array.isArray(source) ? [] : {}
// for(let key in source) {
// target[key] = clone(source[key])
// }
// return target
// } else {
// return source
// }
// }
let obj1 = clone(obj)
obj.info.like = '222334'
console.log('-----------------------------', obj1);
创造对象
// 创建对象的几种方式
// 1、Object.create
// 缺点: 代码麻烦
let obj1 = Object.create({});
obj1.name = '章三';
// 字面量 缺点代码重复
let obj2_1 = {
name: '章三'
};
let obj2_2 = {
name: '里斯'
};
// console.log(obj2_1, obj2_2);
// 工厂模式 代码可以复用
// 缺点: 没法确定类型,因为最终得到的都是对象
function createPerson(name, age) {
let obj = {
name: name,
age: age
};
return obj;
}
let obj31 = createPerson('章三', 12);
let obj32 = createPerson('李四', 13);
function createCat(name, age) {
let obj = {
name: name,
age: age
};
return obj;
}
let obj32 = createCat('李四', 13);
// 自定义函数
// 缺点: getName的代码一样,但是必须复写,占用内存
function createPerson1(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
function createPerson2(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
// 构造函数
function createPerson3(name) {
this.name = name;
}
createPerson3.prototype.getName = function() {
return this.name;
};
防抖截流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="debounce">防抖</button>
<button id="throttle">截流</button>
<script>
// 防抖和截流
// 防抖是每一次都清空之前的,重新开始
// 截流是在同一个时间,不管操作几次,都只执行第一次的操作
document.getElementById("debounce").addEventListener('click', debounce(() => {
console.log('-----------------------------', 11233);
}, 2000))
function debounce(fn, delay) {
let timer = null;
return function() {
timer && clearTimeout(timer)
timer = setTimeout(() => {
fn.call(this)
}, delay);
}
}
document.getElementById("throttle").addEventListener('click', throttle(() => {
console.log('--------------截流---------------');
}, 1000))
function throttle(fn, time) {
let start = true
return function () {
if (!start) return false;
start = false
let timer = setTimeout(() => {
console.log('======this', this)
fn.call(this)
start = true
}, time)
}
}
</script>
</body>
</html>
继承
// 继承的方式
/**
* 原型继承
* 公用一个原型,重复声明实例会污染对方
*/
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function() {
console.log('====1---1', this.name);
return this.name;
};
Person.prototype.setName = function(name) {
this.name = name;
console.log(this.name);
return this.name;
};
function Child(name, age) {
this.name = name;
this.age = age;
}
Child.prototype = new Person('爸爸', 40);
Child.prototype.constructor = Child;
Child.prototype.getAge = function() {
console.log(this.age);
return this.age;
};
let person = new Person('baba', 40);
let child = new Child('孩子', 10);
let child1_1 = new Child('孩子111', 10);
child.setName('hahahah');
child1_1.getName();
/**
* 构造函数继承
* 只能继承属性
*/
function Person1(name, age) {
this.name = name;
this.age = age;
}
Person1.prototype.getName = function() {
console.log(this.name);
return this.name;
};
function Child1(name, age, like) {
Person1.call(this, name, age);
}
Child1.prototype.getAge = function() {
console.log('===1', this.age);
return this.age;
};
let child1 = new Child1('孩子', 10);
// child1.getName();
child1.getAge();
/**
* 组合继承
*/
function Person3(name, age) {
this.name = name;
this.age = age;
}
Person3.prototype.getName = function() {
console.log('====3-name', this.name);
return this.name;
};
function Child3(name, age, like) {
Person3.call(this, name, age);
}
Child3.prototype = new Person3();
Child3.prototype.constructor = Child3;
Child3.prototype.getAge = function() {
console.log('===3', this.age);
return this.age;
};
let child3 = new Child3('孩子', 10);
child3.getName();
/**
* 组合寄生继承
*/
function Person4(name, age) {
this.name = name;
this.age = age;
}
Person4.prototype.getName = function() {
console.log('====4-name', this.name);
return this.name;
};
function Child4(name, age, like) {
Person4.call(this, name, age);
}
Child4.prototype = Object.create(Person4.prototype);
Child4.prototype.constructor = Child4;
Child4.prototype.getAge = function() {
console.log('===4', this.age);
return this.age;
};
let child4 = new Child4('孩子4', 10);
child4.getName();
new
/**
* new 的原理
*/
function Person(name, age) {
this.name = name;
this.age = age
}
Person.prototype.play = function() {
console.log('play');
}
function _new(clazz, ...args) {
let obj = {}
obj.__proto__ = clazz.prototype; // 关联原型
clazz.call(obj, ...args)
return obj
}
const lili = _new(Person, '丽丽', 10) // new Person('丽丽', 10)
lili.play()
限制并发请求数量
class Limit {
constructor(max) {
this.tasks = [];
this.max = max || 6;
setTimeout(() => {
this.start();
}, 0);
}
addTask(task) {
this.tasks.push(task);
}
start() {
if (this.tasks.length === 0) return;
let min = Math.min(this.tasks.length, this.max);
for (let i = 0; i < min; i++) {
this.max--;
let task = this.tasks.shift(); // 从数组头部取任务
task()
.then((res) => {
console.log(res);
})
.finally(() => {
this.max++; // 超过最大并发6后的任务将按照任务顺序依次执行。此处可理解为递归操作。
this.start();
});
}
}
}
let q = new Limit();
for (let i = 0; i < 10; i++) {
q.addTask(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功' + i);
}, 1000);
});
});
}
类数组
类数组具有length属性,但是没有Arrary的原型方法
-
- 使用
Array.from()
- 使用
-
- 使用
Array.prototype.slice.call()
- 使用
-
- 使用
Array.prototype.forEach()进行属性遍历并组成新的数组
- 使用
let obj = {
length: 2,
0: 1,
a: 2,
'-2': 3,
3: 3
};
console.log(Array.from(obj)); // [ 1, undefined ]
忽略不是数字和和非整数的属性,按照length生成,并且自动填充
node
nodejs的轮询机制
- timers: 处理setInterval, setTimeout
- pedding callbacks:系统的回调函数
- idle, prepare node内部使用
- poll
- 进入时有回调函数,就处理回调,当回调函数处理完或者系统达到最大的限制之后,跳过当前进入check
- 进入时没有回调函数,等待回调函数,同时检测timers阶段是不是有超时的回调,有就进入check
- check: 处理setImmediate的回调
- close callbacks: 这个阶段用来处理如socket的close事件