构造函数实例化强制new
function A(n) {this.name=nif (new.target == A) {console.log(1)return new A(n)}else {console.log(2)return new A(n)}}var a= A(54)console.log(a)
函数柯里化
function curry(f){return function curried(...args){if(args.length==f.length){return f.apply(null,args)}else{return function(...args2){return curried.apply(this, args.concat(args2));}}}}var a=curry(pan)console.log(a(1)(2)(3)(4))function pan(a,b,c,d){return a+b+c+d}console.log(pan.length)
深拷贝
对象
// 方法1版本一function Copy(obj){if(typeof obj=='object'){var subif(obj instanceof Array){sub=[]}else{sub={}}for (val in obj){sub[val]=Copy(obj[val])}return sub}else{return obj}}// 方法1版本二function Copy(obj){var subif(obj.constructor==Object){sub={}for (val in obj){sub[val]=Copy(obj[val])}return sub}else if(obj.constructor==Array){sub=[]for (val in obj){sub[val]=Copy(obj[val])}return sub}else{return obj}}// 方法2function Copy(obj){return JSON.parse(JSON.stringify(obj))}var a=[1,2,[3,4],5]var b={a:[1,2],b:{c:3},d:4}function pan(){}var c=[1,pan]var a1=Copy(a)var b1=Copy(b)var c1=Copy(c)//console.log(a1,b1,c1)
数组
并非实现内部对象深拷贝,是只针对数据内基本类型的拷贝
// 并非对象深拷贝,是只针对数据内基本类型的拷贝// 方法一:for循环//方法二function arrCopy(arr){var [...temp]=arrreturn [...temp]}function arrCopy(arr){return Array.from(arr)}function arrCopy(arr){return arr.slice()}function arrCopy(arr){return [].concat(arr)}function arrCopy(arr){return Object.assign(arr)}var a=[1,2,3,[4],5]var b={a:[1,2],b:{c:3},d:4}var a1=arrCopy(a)console.log(a1)console.log(a1[3]==a[3])
async实现
function myAsync(generator) {return new Promise((res, rej) => {// 初始化阶段var iterator = generator()var generated = iterator.next()function step() {if (generated.done) {Promise.resolve(generated.value).then(res)console.log('done')} else {Promise.resolve(generated.value).then(val => {console.log(val)generated = iterator.next(val)step()})}}step()})}// 完整版// function myAsync(generator) {// return new Promise((res, rej) => {// // 初始化阶段// var iterator = generator()// var generated// try {// generated = iterator.next()// } catch (err) {// rej(err)// }// function step() {// if (generated.done) {// Promise.resolve(generated.value).then(res)// console.log('done')// } else {// Promise.resolve(generated.value).then(val => {// console.log(val)// try {// generated = iterator.next(val)// } catch (err) {// rej(err)// }// step()// }, reason => {// try {// generated = iterator.throw(reason)// } catch (err) {// rej(err)// }// })// }// }// step()// })// }// 实验function* pan() {var a = yield console.log(5)var b = yield new Promise((res) => {setTimeout(() => {console.log(6);res(6)}, 1000)})var c = yield console.log(7);}myAsync(pan)console.log(111)
bind实现
Function.prototype.myBind = function (thisArg, ...fixedArgs) {var self = thisreturn function newFnc(...args) {// 考虑将bind之后的函数作为构造函数使用// if(new.target==newFnc){// return new self(...fixedArgs,...args)// }// else{return self.call(thisArg, ...fixedArgs, ...args)// }}}
event类观察者模式
class Event {constructor () {this.handlers = {}}addEventListener (type, handler) {// 首先判断handlers内有没有type事件容器,没有则创建一个新数组容器if (!(type in this.handlers)) {this.handlers[type] = []}// 将事件存入this.handlers[type].push(handler)}// 触发事件两个参数(事件名,参数)dispatchEvent (type, ...params) {// 若没有注册该事件则抛出错误if (!(type in this.handlers)) {return new Error('未注册该事件')}// 便利触发this.handlers[type].forEach(handler => {handler(...params)})}// 事件移除参数(事件名,删除的事件,若无第二个参数则删除该事件的订阅和发布)removeEventListener (type, handler) {// 无效事件抛出if (!(type in this.handlers)) {return new Error('无效事件')}if (!handler) {// 直接移除事件delete this.handlers[type]} else {const idx = this.handlers[type].findIndex(ele => ele === handler)// 抛出异常事件if (idx === undefined) {return new Error('无该绑定事件')}// 移除事件this.handlers[type].splice(idx, 1)if (this.handlers[type].length === 0) {delete this.handlers[type]}}}}var event = new Event() // 创建event实例// 定义一个自定义事件:"load"function load (params) {console.log('load', params)}event.addEventListener('load', load)// 再定义一个load事件function load2 (params) {console.log('load2', params)}event.addEventListener('load', load2)// 触发该事件event.dispatchEvent('load', 'load事件触发')// 移除load2事件event.removeEventListener('load', load2)// 移除所有load事件event.removeEventListener('load')
new

function myNew(f,...args){// var mythis = Object.create(f.prototype)//等同于下几句var mythis={}mythis.__proto__=f.prototypevar res=f.apply(mythis,args)if (res && typeof res=='object'){console.log(res==mythis)return res}else{console.log(res==mythis)return mythis}}function Person(name){this.name=namereturn this}console.log(myNew(Person,'hello'))
InstanceOf
function myInstanceOf(a,b){if(a.__proto__==null){return false}// if(a.constructor=b){if(a.__proto__==b.prototype){return true}else{return myInstanceOf(a.__proto__,b)}}console.log(myInstanceOf([],Function))
Object.create
function create(obj){function F(){}F.prototype=objreturn new F()}function create(obj){var a={}a.__proto__=objreturn a}console.log(create({a:123}))
promisify & callbackify
function promisify(callbackFun){return function p(...args){return new Promise((res,rej)=>{callbackFun(...args,(err,data)=>{if(err){rej(err)}else{res(data)}})})}}var p=promisify(cb)p(...args).then()function callbackify(promise){return function (...args){var callback=args.pop()promise(...args).then(data=>{callback(null,data)}).catch(err=>{callback(err)})}}var cb=callbackify(p)cb(...args,(err,data)=>{})
useEffect & useState
// useStateconst React = (function () {let stateValuereturn Object.assign(React, {useState(initialStateValue) {stateValue = stateValue || initialStateValuefunction setState(value) {stateValue = value}return [stateValue, setState]}})})()//useEffectconst React = (function () {let depsreturn Object.assign(React, {useEffect(callback, depsArray) {const shouldUpdate = !depsArrayconst depsChange = deps ? !deps.every((depItem, index) => depItem === depsArray[index]) : trueif (shouldUpdate || depsChange) {callback()deps = depsArray || []}}})})()
event类观察者模式
class Event {constructor () {this.handlers = {}}addEventListener (type, handler) {// 首先判断handlers内有没有type事件容器,没有则创建一个新数组容器if (!(type in this.handlers)) {this.handlers[type] = []}// 将事件存入this.handlers[type].push(handler)}// 触发事件两个参数(事件名,参数)dispatchEvent (type, ...params) {// 若没有注册该事件则抛出错误if (!(type in this.handlers)) {return new Error('未注册该事件')}// 便利触发this.handlers[type].forEach(handler => {handler(...params)})}// 事件移除参数(事件名,删除的事件,若无第二个参数则删除该事件的订阅和发布)removeEventListener (type, handler) {// 无效事件抛出if (!(type in this.handlers)) {return new Error('无效事件')}if (!handler) {// 直接移除事件delete this.handlers[type]} else {const idx = this.handlers[type].findIndex(ele => ele === handler)// 抛出异常事件if (idx === undefined) {return new Error('无该绑定事件')}// 移除事件this.handlers[type].splice(idx, 1)if (this.handlers[type].length === 0) {delete this.handlers[type]}}}}var event = new Event() // 创建event实例// 定义一个自定义事件:"load"function load (params) {console.log('load', params)}event.addEventListener('load', load)// 再定义一个load事件function load2 (params) {console.log('load2', params)}event.addEventListener('load', load2)// 触发该事件event.dispatchEvent('load', 'load事件触发')// 移除load2事件event.removeEventListener('load', load2)// 移除所有load事件event.removeEventListener('load')
发布-订阅模式
它的优点是为时间是解耦,为对象之间解构,它的应用非常广泛,既可以在异步编程中也可以帮助我们完成更松的解耦。发布-订阅模式还可以帮助我们实现设计模式,从架构上来看,无论MVC还是MVVC都少不了发布-订阅模式的参与。
发布-订阅模式也存在一些缺点,创建订阅本身会消耗一定的时间与内存,也许当你订阅一个消息之后,之后可能就不会发生。发布-订阅模式虽然它弱化了对象与对象之间的关系,但是如果过度使用,对象与对象的必要联系就会被深埋,会导致程序难以跟踪与维护。
案例
//发布-订阅//有个消息池,存放所有消息let pubsub = {};(function(myObj) {topics = {}subId = -1;//订阅者接受参数:(消息名称,回调函数)myObj.subscribe = function(topic, func) {//如果订阅的该事件还未定义,初始化if (!topics[topic]) {topics[topic] = []}//使用不同的token来作为订阅者的索引let token = (++subId).toString()topics[topic].push({token: token,func: func})return token}//发布者接受参数(消息名称,参数)myObj.publish = function(topic, msg) {//如果发布的该消息没有订阅者,直接返回if (!topics[topic]) {return}//对该消息的所有订阅者,遍历去执行各自的回调函数let subs = topics[topic]subs.forEach(function(sub) {sub.func(topic, msg)})}myObj.unsubscribe = function(token) {//对消息列表遍历查找该token是哪个消息中的哪个订阅者for (let t in topics) {//对象原型上的属性不予以使用if(!topics.hasOwnProperty(t)) returntopics[t].forEach(function(sub,index) {if (sub.token === token) {//找到了,从订阅者的数组中去掉该订阅者topics[t].splice(index, 1)}})}}})(pubsub)let sub1 = pubsub.subscribe('Msg::Name', function(topic, msg) {console.log("event is :" + topic + "; data is :" + msg)});let sub2 = pubsub.subscribe('Msg::Name', function(topic, msg) {console.log("this is another subscriber, data is :" + msg)});pubsub.publish('Msg::Name', '123')pubsub.unsubscribe(sub2)pubsub.publish('Msg::Name', '456')
其中存储消息的结构用json可以表示为:
topics = {
topic1: [{ token: 1, func: callback1 }, { token: 2, func: callback2 }],
topic2: [{ token: 3, func: callback3 }, { token: 4, func: callback4 }],
topic3: []
}
与事件监听模式
消息池的结构是发布订阅模式与事件监听模式的最大区别。当然,每个消息也可以看做是一个个的事件,topics对象就相当于一个事件处理中心,每个事件都有各自的订阅者。所以事件监听其实就是发布订阅模式的一个简化版本。而发布订阅模式的优点就是我们可以查看消息中心的信息,了解有多少信号,每个信号有多少订阅者。
与观察者模式
很多情况下,我们都将观察者模式和发布-订阅模式混为一谈,因为都可用来进行异步通信,实现代码的解耦,而不再细究其不同,但是内部实现还是有很多不同的。
- 整体模型的不同:发布订阅模式是靠信息池作为发布者和订阅者的中转站的,订阅者订阅的是信息池中的某个信息;而观察者模式是直接将订阅者订阅到发布者内部的,目标对象需要负责维护观察者,也就是观察者模式中订阅者是依赖发布者的。
- 触发回调的方式不同:发布-订阅模式中,订阅者通过监听特定消息来触发回调;而观察者模式是发布者暴露一个接口(方法),当目标对象发生变化时调用此接口,以保持自身状态的及时改变。
观察者模式很好的应用是MVC架构,当数据模型更新时,视图也发生变化。从数据模型中将视图解耦出来,从而减少了依赖。但是当观察者数量上升时,性能会有显著下降。
//观察者模式
var Subject=function(){
this.observers=[];
}
Subject.prototype={
subscribe:function(observer){
this.observers.push(observer);
},
unsubscribe:function(observer){
var index=this.observers.indexOf(observer);
if (index>-1) {
this.observers.splice(index,1);
}
},
notify:function(observer,msg){
var index=this.observers.indexOf(observer);
if (index>-1) {
this.observers[index].notify(msg)
}
},
notifyAll:function(msg){
this.observers.forEach(function(observe,msg){
observe.notify(msg)
})
}
}
var Observer=function(){
return {
notify:function(msg){
console.log("received: "+msg);
}
}
}
var subject=new Subject();
var observer0=new Observer();
var observer1=new Observer();
var observer2=new Observer();
var observer3=new Observer();
subject.subscribe(observer0);
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.subscribe(observer3);
subject.notifyAll('all notified');
subject.notify(observer2,'asda');
Promise实现
class Promise {
constructor(executor) {
//每个promise实例均有
// state、
// value、
// reason、
// res队列、
// rej队列
//这几个实例属性
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
//针对的是
//promise1.then(a)
//promise1.then(b)
//等同一个promise的多个then非链式调用
this.onResolvedCallbacks.forEach(fn => fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
//x为then函数内部返回值,promise2为新创建的promise,
//resolvePromise可处理x为promise的情况,并可以递归等待状态resolve
//当x不是promise,将promise2的最终value设为x
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
});
};
});
return promise2;
}
catch(fn) {
return this.then(null, fn);
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called;
//函数视同对象
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, err => {
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
// resolve方法
Promise.resolve = function (val) {
return new Promise((resolve, reject) => {
resolve(val)
});
}
//reject方法
Promise.reject = function (val) {
return new Promise((resolve, reject) => {
reject(val)
});
}
//race方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject)
};
})
}
//all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
Promise.all = function (promises) {
let arr = [];
let i = 0;
function processData(index, data) {
arr[index] = data;
i++;
if (i == promises.length) {
resolve(arr);
};
};
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(data => {
processData(i, data);
}, reject);
};
});
}
// console.log(
new Promise((res, rej) => {
res(1)
})
.then(data => {
console.log(2)
console.log('data', data)
// return 999
}).then(res => {
console.log('res', res);
})
// )
Lazy
function lazy(f) {
return class Lazy extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true
}
f().then(Comp => {
this.Comp = Comp
this.setState({
loading: false
})
})
}
render() {
if (this.state.loading) {
return null
} else {
var Comp = this.Comp
var {children, ...props} = this.props
return <Comp {...props}>{children}</Comp>
}
}
}
}
var Comp = React.lazy2({
compoent: () => import('./MyComponent'),
loading: (props) => {
return <div>loading...</div>
},
error: (props) => {
return <div>error</div>
},
timeout: 3000,
delay: 200,
})
function lazy(f) {
class Lazy extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true
}
f().then(Comp => {
this.Comp = Comp
this.setState({
loading: false
})
})
}
render() {
if (this.state.loading) {
return <span style={{color:'red'}}>loading...</span>
} else {
var Comp = this.Comp
var {children, forwardRef, ...props} = this.props
return <Comp ref={forwardRef} {...props}>{children}</Comp>
}
}
}
return React.forwardRef((props, ref) => {
return <Lazy {...props} forwardRef={ref}/>
})
}
React.lazy2 = function(obj) {
return function LazyComp(props) {
var [delay, setDelay] = useState(false)
setTimeout(() => {
setDelay(true)
}, obj.delay)
var [error, setError] = useState(false)
var [timeout, setTO] = useState(false)
setTimeout(() => {
setDelay(true)
}, obj.timeout)
var [loading, setLoading] = useState(false)
var [ActuralComp, setActuralComp] = useState(null)
obj.compoent().then(comp => {
setLoading(false)
setActuralComp(comp)
}).catch(() => {
setError(true)
})
if (error) {
var Loading = obj.loading
return <Loading {...props}/>
}
if (delay) {
var Delay = obj.delay
return <Delay {...props}/>
}
if (loading) {
return null
} else {
return <ActuralComp {...props}/>
}
}
}
Lazyman
function LazyMan(name) {
return new _LazyMan(name)
}
class _LazyMan {
constructor(name) {
this.name = () => {
console.log(name)
}
this.tasks = [this.name]
this.time = null
this.run.call(this)
//ES6的class只能通过new来使用,不能直接运行。
// if(new.target!=LayMan){
// return this
// }
}
run() {
if (this.time) {
clearTimeout(this.time)
this.time = null
}
this.time = setTimeout(async () => {
for (var task of this.tasks) {
await task()
}
})
}
eat(event) {
var task = () => {
console.log(event)
}
this.tasks.push(task)
return this
}
sleep(num) {
var task = () => {
return new Promise((res,rej)=>{
setTimeout(()=>{
res()
console.log('Wake up after '+num)
},num*1000)
})
}
this.tasks.push(task)
return this
}
sleepFirst(num) {
var task = () => {
return new Promise((res,rej)=>{
setTimeout(()=>{
res()
console.log('Wake up after '+num)
},num*1000)
})
}
this.tasks.unshift(task)
return this
}
}
// LazyMan('Hank').eat('dinner').eat('supper')
// LazyMan('Hank').sleep(5).eat('dinner')
LazyMan('Hank').sleepFirst(5).eat('supper')

