class Person{
constructor(name,age){
this.name = name
this.age = age
}
eat(){
console.log(`${this.name} eat something`)
}
speak(){
console.log(`My name is ${this.name}, age ${this.age}`)
}
}
//继承
class Student extends Person{
constructor(name,age,number){
super(name,age)
this.number = number
}
study(){
console.log(`${this.number}号${this.name}同学正在学习`)
}
}
let han = new Student('han',20,20)
han.eat()
han.speak()
han.study()
封装
//ts运行环境
class People {
name
age
protected weight
constructor(name, age) {
this.name = name
this.age = age
this.weight = 120
}
eat(){
console.log(`${this.name} eat something`)
}
speak(){
console.log(`My name is ${this.name}, age ${this.age}`)
}
}
//继承
class Student extends People{
number
private girlfriend
constructor(name,age,number){
super(name,age)
this.number = number
this.girlfriend = 'xiaoli'
}
study(){
console.log(`${this.number}号${this.name}同学正在学习`)
}
getWeight() {
console.log(`weight ${this.weight}`)
}
}
let xiaoming = new Student('xiaoming', 20, 'A1')
xiaoming.getWeight()
console.log(xiaoming.girlfriend)//这里会报错 girlfriend是私有的
console.log(xiaoming.weight)//这里会报错 weight只能由类本身和子类来读取
多态
class People{
constructor(name){
this.name = name
}
}
class A extends People{
constructor(name){
super(name)
this.name = name
}
saySomething(){
alert('I am A')
}
}
class B extends People{
constructor(name){
super(name)
this.name = name
}
saySomething(){
alert('I am B')
}
}
let a = new A()
a.saySomething()//I am A
let b = new B()
b.saySomething()//I am B
ES6 模拟 jQuery
class jQuery{
constructor(seletor){
let slice = Array.prototype.slice
let dom = slice.call(document.querySelectorAll(seletor))//遍历dom获取seletor节点
let len = dom ? dom.length : 0
for(let i = 0;i < len;i++){
this[i] = dom[i]
}
this.length = len
this.seletor = seletor || ''
}
append(node){
}
addClass(name){
}
html(node){
}
//此处省略N个API
}
window.$ = function(seletor){
return new jQuery(seletor)
}
var $p = $('p')
console.log($p)
console.log($p.addClass)
UML 类图
属性、方法前的+#-代表着公共、继承和私有
设计原则
设计模式=设计+模式 设计=设计原则
何谓设计
即按照哪一种四路或者标准来实现业务功能
功能相同,可以有不同的设计方案来实现
伴随需求增加,设计的作用才能体现出来
设计准则
准则 1:小即是美
准则 2:让每个程序只做好一件事
准则 3:快速建立原型
准则 4:舍弃高效率而取可移植性
准则 5:采用纯文本来存储数据
准则 6:充分利用软件的杠杆效应(重复利用)
准则 7:使用 shell 脚本来提高杠杆效应的可移植性
准则 8:避免强制性的用户界面
准则 9:让每个程序都成为过滤器
小准则:允许用户定制环境
小准则:尽量使操作系统内核小而轻量化
小准则:使用小写字母并尽量简短
小准则:沉默是金
小准则:各部分之和大于整体
小准则:寻求 90%的解决方案(二八定律)
SOLID 五大设计原则
S 单一职责原则(single)
O 开放封闭原则(open-close)
L 李氏置换原则(Liskov Substitution Principle: LSP)
I 接口独立原则(interface)
D 依赖导致原则(Dependence Inversion Principle)
用 Promise 来说明 SO
function loadImg(src){
let promise = new Promise((resolve, reject) => {
let img = document.createElement('img')
img.onload = function(){
resolve(img)
}
img.onerror = function(){
reject('图片加载失败')
}
img.src = src
});
return promise
}
let src = 'https://www.hansuku.com/wp-content/themes/Lover/images/thumbs/5.jpg'
let result = loadImg(src)
result.then(img=>{
//part1
alert(`width:${img.width}`)
return img
}).then(img=>{
//part2
alert(`height:${img.height}`)
}).catch(ex=>{
alert(ex)
})
//每增加一个需求就加一个then,一个then只做一件事
class Car{
constructor(num){
this.num = num
}
}
class ParkLot{
constructor(floors){
this.floors = floors || []
this.carList = {} //存储拍摄返回的信息
this.camera = new Camera()
this.screen = new Screen()
}
emptyNum(){
return this.floors.map(floor=>{
return `${floor.index} 层还有 ${floor.emptyPlaceNum()} 个空闲车位`
}).join('\n')
}
in(car){
//通过摄像头获取信息
const info = this.camera.shot(car)
//听到某个停车场
const i = parseInt(Math.random() * 100 % 100)
const place = this.floors[0].places[i]
place.in()
info.place = place
//记录信息
this.carList[car.num] = info
}
out(car){
//获取信息
const info = this.carList[car.num]
const place = info.place
place.out()
//显示时间
this.screen.show(car,info.inTime)
delete this.carList[car.num]
}
}
class Camera{
constructor(car){
this.car = car
}
shot(car){
return{
num: car.num,
inTime: Date.now()
}
}
}
class Screen{
show(car,inTime){
console.log('车牌号',car.num)
console.log('停车时间',Date.now() - inTime)
}
}
class Floor{
constructor(index,places){
this.index = index
this.places = places || []
}
emptyPlaceNum(){
let num = 0
this.places.forEach(p=>{
if(p.empty){
num = num+1
}
})
return num
}
}
class Place{
constructor(){
this.empty = true
}
in(){
this.empty = false
}
out(){
this.empty = true
}
}
//初始化停车场
const floors = []
for(let i = 0;i < 3;i++){
const places = []
for(let j = 0;j < 100;j++){
places[j] = new Place()
}
floors[i] = new Floor(i+1,places)
}
const park = new ParkLot(floors)
//初始化车辆
const car1 = new Car(100)
const car2 = new Car(200)
const car3 = new Car(300)
console.log('第一辆车进入')
console.log(park.emptyNum())
park.in(car1)
console.log('第二辆车进入')
console.log(park.emptyNum())
park.in(car2)
console.log('第一辆车离开')
park.out(car1)
console.log('第三辆车进入')
console.log(park.emptyNum())
park.in(car3)
console.log('第二辆车离开')
park.out(car2)
console.log('第三辆车离开')
park.out(car3)
console.log(park.emptyNum())
工厂模式
工程模式意在把所有类都封装到一个创建者上,通过创建者调用类 类似jQuery:window.$ = function(seletor){return new jQuery(seletor)}这里就是构造者,使用者不需要new jQuery("p")而可以直接调用$('p')
class Product{
constructor(name){
this.name = name
}
init(){
alert('init')
}
fn1(){
alert('fn1')
}
fn2(){
alert('fn2')
}
}
class Creator{
create(name){
return new Product(name)
}
}
let creator = new Creator()
let p = creator.create('p1')
p.init()
p.fn1()
单例模式
单例模式意在每个 class 只能 new 一次 比如下面的代码 obj1 和 obj2 虽然都 new 了 SingleObject 但是他们两个是完全相等的 而简单的 JS 不能够实现类似 java 那样完全拒绝重复 new 下面的代码中,obj3 是一个 new 出来的 SingleObject,虽然不会报错,但是这个时候会发现 obj1 != obj3
class SingleObject{
login(){
console.log('login')
}
}
SingleObject.getInstance = (function(){
let instance
return function(){
if(!instance){
instance = new SingleObject()
}
return instance
}
})()
let obj1 = SingleObject.getInstance()
obj1.login()
let obj2 = SingleObject.getInstance()
obj2.login()
console.log(obj1 === obj2)
let obj3 = new SingleObject() //无法完全控制
obj3.login()
console.log(obj1 === obj3) //false
class Adaptee{
specificRequest(){
return '德国标准插头'
}
}
class Target{
constructor(){
this.adaptee = new Adaptee()
}
request(){
let info = this.adaptee.specificRequest()
return `${info} - 转换器 - 中国标准插头`
}
}
let target = new Target()
let res = target.request()
console.log(res) //德国标准插头 - 转换器 - 中国标准插头
class Circle{
draw(){
console.log('画一个圆形')
}
}
class Decorator{
constructor(circle){
this.circle = circle
}
draw(){
this.circle.draw()
this.setRedBorder(circle)
}
setRedBorder(circle){
console.log('设置红色边框')
}
}
//test
let circle = new Circle()
circle.draw()
let dec = new Decorator(circle)
dec.draw()
@testDec
class Demo{
}
function testDec(target){
target.isDec = true
}
console.log(Demo.isDec)
@decorator
class A {}
//等同于
class A {}
A = decorator(A) || A;
只读装饰器
function readonly(target,name,descriptor){
descriptor.writable = false
return descriptor
}
class Person{
constructor(){
this.first = 'A'
this.last = 'B'
}
@readonly
name(){
return `${this.first} ${this.last}`
}
}
let p = new Person()
console.log(p.name())
// p.name = function(){ //这里会报错,name是只读的
// alert(100)
// }
function log(target,name,descriptor){
let oldValue = descriptor.value
descriptor.value = function(){
console.log(`calling ${name} with`,arguments)
return oldValue.apply(this, arguments)
}
return descriptor
}
class Math{
@log
add(a,b){
return a + b
}
}
let math = new Math()
const result = math.add(2,4)
console.log(result)//会在返回相加值前打印arguments
使用插件预设的装饰器
//安装 npm install core-decorators --save
import { readonly } from 'core-decorators'
class Person{
@readonly
name(){
return 'zhang san'
}
}
let p = new Person()
alert(p.name())
p.name = function(){} //只读报错
import { deprecate } from 'core-decorators'
class Person{
@deprecate('该接口即将废除')
name(){
return 'zhang san'
}
}
let p = new Person()
console.log(p.name())//提示该接口即将废除
代理模式
class RealImg{
constructor(filename){
this.filename = filename
this.loadFromDisk() //从硬盘中加载 模拟
}
display(){
console.log('display'+this.filename)
}
loadFromDisk(){
console.log('loading...'+this.filename)
}
}
class ProxyImg{
constructor(filename){
this.realImg = new RealImg(filename)
}
display(){
this.realImg.display()
}
}
let proimg = new ProxyImg('1.png')
proimg.display()
var src = 'https://image.biadu.com/1.png'
var result = loadImg(src)
result.then(function(img){
console.log('width',img.width)
return img
}).then(function(img){
console.log('height',img.height)
})
NodeJs 自定义事件
const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()
//监听 some 事件
emitter1.on('some',info=>{
console.log('fn1', info)
})
//监听 some 事件
emitter1.on('some',info=>{
console.log('fn2', info)
})
//触发 some 事件
emitter1.emit('some','xxxx')
// 继承
const EventEmitter = require('events').EventEmitter
class Doc extends EventEmitter{
constructor(name){
super()
this.name = name
}
}
let simon = new Dog('simon')
simon.on('brak',function(){
console.log(this.name, 'barked_1')
})
simon.on('brak',function(){
console.log(this.name, 'barked_2')
})
setInterval(function(){
simon.emit('bark')
},1000)
//stream 用到自定义事件 fs分段加载文件
const fs = require('fs')
const readStream = fs.createReadStream('./a_big_file')
let length = 0
readStream.on('data',function(chunk){
let len = chunk.toString().length
length += len
console.log(len)
})
readStream.on('end',function(){
console.log('length',length)
})