function myPromise(executor){
this.status='pending';
this.value=null;
this.reason=null;
this.onFulfilledCallbacks=[];
this.onRejectedCallbacks=[];
function resolve(value){
if(this.status=='pending'){
this.status='fulfilled';
this.value=value;
this.onFulfilledCallbacks.forEach(item=>{item(value)});
}
}
function reject(reason){
if(this.status=='pending'){
this.status='rejected';
this.reason=reason;
this.onRejectedCallbacks.forEach(item=>{item(reason)});
}
}
executor&&executor(resolve,reject);
}
myPromise.prototype.then(onFulfilled,onRejected){
onFulfilled= typeof onFulfilled=='function'?onFulfilled:data=>data;
onRejected=typeof onRejected=='function'?onRejected:err=>throw err;
if(this.status=='fulfilled'){
resolve(this.value);
}
if(this.status=='rejected'){
reject(this.reason);
}
if(this.status=='pending'){
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
}
function promiseAll(promises){//给每个请求增加自己的catch,避免promiseall.catch提前跳出
return new Promise(resolve,reject){
if(!Array.isArray(Array.from(promises))) throw TypeError('error');
let counter=0,Interator=0,result=[];
for(let i of promises){
interator++;
Promise.resolve(i).then(value=>{
counter++;
results.push(value);
if(counter==Interator){
resolve(results);
}
},err=>return reject(err))
}
}
}
function promiseRace(promises) {
return new Promise((resolve,reject) => {
if(!Array.isArray(Array.from(promises))) throw TypeError('error');
for (const p of promises) {
Promise.resolve(p)
.then((res) => {
resolve(res)
})
.catch(e => {
reject(e)
})
}
})
}
手写repeat
function myrepeat(fn,times,timeout){
return function(content){
let count=0;
let timer=setInterval({
count++;
fn(content);
if(count==times) clearInterval(timer);
},timeout)
}
}
let repeat1=myrepeat(console.log,4,2000);
repeat1('1')
var oli = document.getElementsByTagName("li");
for(var i=0; i<oli.length; i++){
(function(j){
oli[j].onclick = function () {
alert(j);
};
})(i)
}
//js事件委托
var ul = document.querySelector("ul");
ulItem.onclick = function (e) {
e = e || window.event; //这一行及下一行是为兼容IE8及以下版本
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === "li") {
var li = this.querySelectorAll("li");
index = Array.prototype.indexOf.call(li, target);
alert(target.innerHTML + index);
}
}
防抖 每次执行重新计时,场景:逐字联想
function debounce(fn,wait){
let timer;
return function(args){
clearInterval(timeout);
timer=setTimeout(()=>{
fn(args);
},wait)
}
}
节流 固定时间内只能执行一次,场景:提交表单
function throttle(fn,wait){
let timer;
return function(args){
if(!timer){
timer=setTimeout(()=>{
timer=null;
fn(args);
},wait)
}
}
}
深拷贝
function deepclone(source){
if(typeof source!=='object') return source;
var obj=Array.isArray(source)?[]:{};
for(let i in source){
obj[i] = typeof source[i] == "object" ? deepclone(source[i]) : source[i];
}
return obj;
}
call 多个参数
Function.prototype.mycall=function(context){
if(typeof this!='function'){
throw new Error('error');
}
context=context||window;
context.fn=this;
var args=[...arguments].slice(1)
return context.fn(...args)
}
apply 两个参数,第二个参数是数组
Function.prototype.myapply=function(context){
if(typeof this!='function'){
throw new Error('error');
}
context=context||window;
context.fn=this;
var args=arguments[1]
return context.fn(...args)
}
bind 返回一个新的函数,必须调用才能执行
Function.prototype.mybind = function (context) {
if(typeof this!='function'){
throw new Error('error');
}
context = context || window;
let args = [...arguments].slice(1);
context.fn = this;
return function () {
context.fn(...args)
}
}
new
Function.prototype.myNew = function () {
let obj = Object.create(this.prototype)//基于原型创建一个新对象
let result = this.call(obj, ...arguments)//继承属性,获取函数执行的结果
return result instance of Object ? result : obj//返回一个对象就返回,不是返回新创建的对象
}
闭包实现单例
function singletone(fn){
let result;
return function(){
result||(result=fn.apply(this,arguments))
}
}
lodash
// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
function basePath(path) {
if (Array.isArray(path)) return path // 若是数组,则直接返回
return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
}
//lodash.get
function get(object, path, defaultValue) {
if (typeof object !== 'object') return defaultValue// 判断 object 是否是数组或者对象,否则直接返回默认值 defaultValue
return basePath(path).reduce((o, k) => (o || {})[k], object) || defaultValue// 沿着路径寻找到对应的值,未找到则返回默认值 defaultValue
}
//lodash.set
function set(object, path, value) {
if (typeof object !== 'object') return object;
basePath(path).reduce((o, k, i, _) => {
if (i === _.length - 1) { // 若遍历结束直接赋值
o[k] = value
return null
} else if (k in o) { // 若存在对应路径,则返回找到的对象,进行下一次遍历
return o[k]
} else { // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
return o[k]
}
}, object)
return object;
}
Array.prototype.flat=function(){
let result=[];
for(let item of this){
if(Array.isArray(item)){
result=result.concat(item.flat())
}else result.push(item);
}
return result;
}
Array.prototype.flat=function(){
let result=this;
while (result.some(item=>Array.isArray(item))){
result=[].concat(...result)
}
return result
}
Promise实现间隔打印
async function timer() {
for (let i = 1; i < 4; i++) {
console.log('ww', await _promise(i))
}
}
function _promise(interval) {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve(interval) }, 1000)
})
}
timer()
async function timer(n) {//传参版
for (let i = 1; i < n; i++) {
console.log('ww', await _promise(i, i * 1000))
}
}
function _promise(num, interval) {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve(num) }, interval)
})
}
timer(4)