function Person(name) { this.name = name; } function Car(model) { this.model = model } // 根据选择的类类型来创建实例对象(只需把类都挂载此工厂函数的原型上,再调用) function createEntity(type,params){ // 如果外部使用了new关键字 if(this instanceof createEntity){ return new this[type](params) }else{// 如果没有使用new关键字 return new createEntity(type,params) } } createEntity.prototype = { Person, Car } console.log(new createEntity('Car','OOOO')); console.log(new createEntity('Person','TOM'));
function Person(name) { this.name = name; } function CreateCar(model) { this.model = model } function CreateHouse(area) { this.area = area } // 构建者模式方便于建立复合对象模型 function personInfo(name,model,area) { let _person = new Person(name) _person.car = new CreateCar(model) _person.area = new CreateHouse(area) return _person } console.log(personInfo('BON','OOOO',360));
// 单例模式,就是都使用创建唯一的一个对象,利用函数闭包实现 let createSingle(function(){ let _unique = null; function single(){ return {a:1} } return function() { if(_unique === null){ _unique = single(); } return _unique } })() console.log(createSingle() === createSingle()) // true
// 希望在不改变原对象的基础上,通过对其拓展功能和属性来实现更复杂的逻辑 function Person(name) { this.name = name; this.wealth = 2 } function createCar(item) { item.car = true item.wealth += 1 } function createHouse(item) { item.house = true item.wealth += 1 } let aa = new Person('name') createCar(aa) createHouse(aa) console.log(aa);
/** * 组合模式就是对经常使用的相同组件的一个封装,利用js创建出来 * 避免了编写重复代码,相当于用作一个插件,快速构建DOM并渲染 * */ function inheritPrototype (superClass,subClass) { const F = function() {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; } function Container(){ this.children = [] this.element = null } Container.prototype = { init: function () { throw new Error("请重写init方法!") }, add: function (child) { this.children.push(this.element) this.element.appendChild(child.element) return this } } function CreateForm(id,method,action,parent) { Container.call(this) this.id = id || '' this.method = method || 'GET' this.action = action || '' this.parent = parent this.init() } inheritPrototype(Container,CreateForm) CreateForm.prototype.init = function () { this.element = document.createElement('form') this.element.id = this.id this.element.method = this.method this.element.action = this.action } CreateForm.prototype.show = function () { this.parent.appendChild(this.element) } function CreateLine(className) { Container.call(this) this.className = className === undefined ? 'form-line' : 'form-line ' + className this.init() } inheritPrototype(Container,CreateLine) CreateLine.prototype.init = function () { this.element = document.createElement('div') this.element.className = this.className } function CreateLabel(text,forName){ this.text = text || '' this.forName = forName this.init() } CreateLabel.prototype.init = function () { this.element = document.createElement('label') this.element.setAttribute('for',this.forName) this.element.innerHTML = this.text } function CreateInput(type,id,name,defaultValue) { this.type = type || '' this.id = id || '' this.name = name || '' this.defaultValue = defaultValue || '' this.init() } CreateInput.prototype.init = function () { this.element = document.createElement('input') this.element.type = this.type this.element.id = this.id this.element.name = this.name this.element.value = this.defaultValue } var form = new CreateForm('owner-form','get','./aa.html',document.body) var userLabel = new CreateLabel('账户','user') var userInput = new CreateInput('text','user','user') var userLine = new CreateLine('user').add(userLabel).add(userInput) var pwdLabel = new CreateLabel('密码','pwd') var pwdInput = new CreateInput('password','pwd','pwd') var pwdLine = new CreateLine('pwd').add(pwdLabel).add(pwdInput) var submitLine = new CreateLine('submit').add(new CreateInput('submit','','','登录')) form.add(userLine).add(pwdLine).add(submitLine).show()
// 订阅者订阅消息==>消息中心,注册订阅者以及接受消息方法函数==>消息中心发布消息,执行订阅者的消息方法函数 const msgCenter = (function() { let _msg = {} return { subscribe(type,fn) { if(_msg[type]){ _msg[type].push(fn) }else{ _msg[type] = [fn] } }, release(type,args = {}) { if(!_msg[type]) return; let event = {type,args}; for(let i = 0; i < _msg[type].length; i++){ _msg[type][i](event); } }, cancel(type,fn) { if(!_msg[type]) return; for(let i = 0; i < _msg[type].length; i++){ if(_msg[type][i] === fn) _msg[type].splice(i,1) } } } })() function Person(name){ this.name = name this.subscribed = {} } Person.prototype.subscribe = function (type,fn) { if(this.subscribed[type]) return; this.subscribed[type] = fn; msgCenter.subscribe(type,fn) } Person.prototype.cancel = function (type) { msgCenter.cancel(type,this.subscribed[type]) if(this.subscribed[type]) delete this.subscribed[type] } let p1 = new Person('p1') p1.subscribe("info_1",(e)=>{ console.log(`${p1.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`); }) p1.subscribe("info_2",(e)=>{ console.log(`${p1.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`); }) let p2 = new Person('p2') p2.subscribe("info_2",(e)=>{ console.log(`${p2.name}:你订阅了 ${e.type},收到的内容是:${e.args.msg}`); }) msgCenter.release('info_1',{msg:'这是msgCenter发布的第一则消息'}) msgCenter.release('info_2',{msg:'这是msgCenter发布的第二则消息'})
// 通过函数闭包,自定义策略来匹配一些模式是否符合规则 function formStrategy(){ let strategy = { isEmpty(value) { return value.length ? '' : 'input some information in here,please' }, isNumber(value) { let reg = /^[0-9]+(\.[0-9]+)?$/; return reg.test(value) ? '' : 'required a type of number at here' }, isPhone(value) { let reg = /^\d{3}-\d{8}$|^\d{4}-\d{7}$/; return reg.test(value) ? '' : 'required a tele-number at here' } } return { validate(type,value){ value = value.replace(/^\s+|\s+$/,'') return strategy[type] ? strategy[type](value) : "there doesn't exit a function,add it manually!" }, addStrategy(type,fn){ if(strategy[type]){ return 'it has this method already' }else { strategy[type] = fn; } } } }
类如jquery的链式调用编程
事件代理(委托)
/** * @params nameSpace|key:expire|value * */ let DataVisitor = function(nameSpace,splitSign) { this.nameSpace = nameSpace this.splitSign = splitSign || '|' } DataVisitor.prototype = { status : { SUCCESS: 0, FAILURE: 1, OVERFLOW: 2, TIMEOUT: 3 }, createKey(key){ return this.nameSpace + this.splitSign + key }, createVal(expire,value){ typeof expire === 'number' ? expire += new Date().getTime() : expire = -1 return expire + this.splitSign + value }, set(key,value,cb,expire){ let status = this.status.SUCCESS key = this.createKey(key); value = this.createVal(expire,value) try{ window.localStorage.setItem(key,value) }catch(e){ status = this.status.OVERFLOW } cb && cb.call(this,status,key,value) return this }, get(key,cb) { let status = this.status.SUCCESS key = this.nameSpace + this.splitSign + key let value = window.localStorage.getItem(key) if(value){ let time = value.slice(0,value.indexOf(this.splitSign)) if(time > new Date().getTime() || time == -1){ value = value.slice(value.indexOf(this.splitSign) + this.splitSign.length) }else{ status = this.status.TIMEOUT value = null window.localStorage.removeItem(key) } }else{ status = this.status.FAILURE } cb && cb.call(this,status,key,value) return this }, remove(key) { let status = this.status.FAILURE key = this.nameSpace + this.splitSign + key let value = this.localStorage.getItem(key) if(value) { value.slice(value.indexOf(this.splitSign) + this.splitSign.length) status = this.status.SUCCESS window.localStorage.removeItem(key) } cb && cb.call(this,status,key,value) return this } } function cb() { console.log(...arguments); } var test = new DataVisitor('test') test.set('aa',123,cb,1000) test.get('aa',cb) setTimeout(() => { test.get('aa',cb) }, 2000);
var MVC = {} MVC.model = (function () { data = { sidebar: [{ title: 'sidebar1', href: './a.html' }, { title: 'sidebar2', href: './b.html' }, { title: 'sidebar3', href: './c.html' }] } return { getData(key){ return data[key] }, setData(key,value){ data[key] = value } } }()) MVC.view = (function () { let m = MVC.model let view = { createDom() { let data = m.getData('sidebar'); let html = ''; html += '<div id="#sidebar">' for(let i = 0; i < data.length; i++) { html += '<div class="side-bar"><a href="'+ data[i].href + '">' + data[i].title + '</a></div>' } html += '</div>'; document.body.innerHTML = html; } } return function(v){ view[v]() } }()) MVC.ctrl = (() => { let m = MVC.model; let v = MVC.view; return { initView(){ v('createDom') }, updateView(){ m.setData('sidebar',[{title: 'newsidebar',href: './n.html'}]) v('createDom') } } })() window.onload = function () { MVC.ctrl.initView() setTimeout(() => { MVC.ctrl.updateView() }, 2000); }
vue数据双向绑定原理
类如promise(期约),状态机改变才会执行对应状态函数