构造函数实例化强制new
function A(n) {
this.name=n
if (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 sub
if(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 sub
if(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
}
}
// 方法2
function 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]=arr
return [...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 = this
return 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.prototype
var 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=name
return 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=obj
return new F()
}
function create(obj){
var a={}
a.__proto__=obj
return 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
// useState
const React = (
function () {
let stateValue
return Object.assign(React, {
useState(initialStateValue) {
stateValue = stateValue || initialStateValue
function setState(value) {
stateValue = value
}
return [stateValue, setState]
}
})
}
)()
//useEffect
const React = (function () {
let deps
return Object.assign(React, {
useEffect(callback, depsArray) {
const shouldUpdate = !depsArray
const depsChange = deps ? !deps.every((depItem, index) => depItem === depsArray[index]) : true
if (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)) return
topics[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')