// 实例如果已经创建,则直接返回
class Person {
info (kg = 60, cm = 174) {
let key = `${kg}kg_${cm}cm`
if (Person.result[key]) {
console.log('已经存在')
return Person.result[key]
} else {
console.log('第一次')
const obj = {height: cm, weight: kg}
Person.result[key] = obj
return obj
}
}
}
Person.result = {}
let a = Person()
a.info()
let b = Person()
b.info()
class GoogleMap {
show () {
console.log('渲染谷歌地图')
}
}
class BaiduMap {
display () {
console.log('渲染百度地图')
}
}
// 定义适配器,进行二次封装
class BaiduMapAdapter {
show () {
const baiduMap = new BaiduMap()
return baiduMap.display()
}
}
function render (map) {
if (map.show instanceof Function) {
map.show()
}
}
let googleMap = new GoogleMap()
let baiduMap = new BaiduMapAdapter()
render(googleMap)
render(baiduMap)
class MyImage {
constructor () {
this.img = new Image()
document.body.appendChild(this.img)
}
// 此方法为方便废弃预加载时,可以直接使用本体的setSrc方法,删除代理类即可
setSrc (src) {
this.img.src = src
}
}
class ProxyImage () {
constructor () {
this.proxyImage = new Image()
}
setSrc (src) {
let myImageObj = new MyImage()
myImageObj.img.src = 'xxxx.png' // 本地路径
this.proxyImage.src = src
this.proxyImage.onload = function () {
myImageObj.img.src = src
}
}
}
let proxyImage = new ProxyImage()
proxyImage.setSrc('http://xxx.png')
const fnA = function (val) {
return val * 1
}
const fnB = function (val) {
return val * 2
}
const fnC = function (val) {
return val * 3
}
var calculate = function (fn, val) {
return fn(val)
}
console.log(calculate(fnA, 100))
console.log(calculate(fnB, 200))
console.log(calculate(fnC, 300))
class Creator {
constructor (list) {
this.list = list
}
createIterator () {
return new Iterator(this)
}
}
class Iterator {
constructor (creator) {
this.list = creator.list
this.keyArr = Object.entries(this.list)
this.index = 0
}
isDone () {
return this.index >= this.keyArr.length
}
next () {
return this.keyArr[this.index++][1]
}
}
const arr = [1, 2, 3, 4]
const obj = {a: 1, b:2}
const creator1 = new Creator(arr)
const iterator1 = creator1.createIterator()
while (!iterator1.isDone()) {
console.log(iterator1.next())
}
const creator2 = new Creator(obj)
const iterator2 = creator2.createIterator()
while (!iterator2.isDone()) {
console.log(iterator2.next())
}
class EventEmitter {
constructor () {
// 缓存列表
this.list = {}
}
// 订阅
on (event, fn) {
// 如果没有event值,就给event创建个缓存列表
// 如果有对应的event值,把fn添加到对应event的缓存列表里
(this.list[event] || (this.list[event] = [])).push(fn)
return this
}
// 监听一次
once (event, fn) {
// 先绑定,调用后删除
function on () {
this.off(event, on)
fn.apply(this, arguments)
}
on.fn = fn
this.on(event, on)
return this
}
// 取消订阅
off (event, fn) {
let fns = this.list[event]
// 如果缓存列表中没有对应的fn,返回false
if (!fns) return false
if (!fn) {
// 如果fn不存在,就会将event值对应缓存列表中的fn都清空
fns && (fns.length = 0)
} else {
// 如果有fn, 遍历缓存列表,看看传入的fn与那个函数相同,如果相同就直接从缓存列表中删除
let cb
let cbLen = fns.length
for (let i = 0; i < cbLen; i++) {
cb = fns[i]
if (cb === fn || cb.fn === fn) {
fns.splice(i, 1)
break
}
}
}
return this
}
// 发布
emit () {
// 第一个参数对应的event值,直接用数组的shift方法取出
let event = [].shift.call(arguments)
let fns = [...this.list[event]]
// 如果缓存列表里没有fn就返回false
if (!fns || fns.length === 0) {
return false
}
// 遍历event值对应的缓存列表,依次执行fn
fns.forEach(fn => {
fn.apply(this, arguments)
})
return this
}
}
// 测试
function user1 (content) {
console.log('用户1订阅了: ', content)
}
function user2 (content) {
console.log('用户2订阅了: ', content)
}
function user3 (content) {
console.log('用户3订阅了: ', content)
}
function user4 (content) {
console.log('用户4订阅了: ', content)
}
let eventEmitter = new EventEmitter()
// 订阅
eventEmitter.on('article1', user1)
eventEmitter.on('article1', user2)
eventEmitter.on('article1', user3)
// 取消user2方法的订阅
eventEmitter.off('article1', user2)
eventEmitter.once('article2', user4)
// 发布
eventEmitter.emit('article1', 'JS 发布-订阅模式')
eventEmitter.emit('article1', 'JS 发布-订阅模式')
eventEmitter.emit('article2', 'JS 观察者模式')
eventEmitter.emit('article2', 'JS 观察者模式')