面向对象: 数据结构化,对代码的一种抽象,对外统一提供调用接口的变成思想。 基于原型的面向对象方式中,对象(object)则是依靠构造器(constructor)利用原型(prototype)构造出来的
函数构造器 创建函数对象
var obj = new Function(var1, var2, ..., functionBody())
var1,var2 正常变量 functionBody()自定义函数
构造器构造的对象,效率低,var1 var2顺序在functionBody中不能变
###闭包 闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数) 用途: 1 读取函数内部变量 2 让内部变量保存在内存中 优点: 有利于封装,可以访问局部变量 缺点: 内存占用浪费严重,内存泄漏
#####构造和工厂模式不同 1. 构造方式不会显示创建对象, 将属性赋值给this, 不需要return对象 2. 工厂在方法内部创建Object对象,返回object对象,属性和方法都是赋值给object
原型模式声明对象 test。prototype。。 让所有的实例共享方法
#####原型和原型链 原型:是利用prototype添加属性和方法 原型链:JS在创建对象(不论是普通对象还是函数对象)的时候,都会有一个叫做`__proto__`的内置属性,用于指向创建他的函数对象的原型对象prototype
创建对象三个阶段 var person = function () {} var p = new person() 三个阶段
- var p = {} 闯将对象
p.__ptoto__ = person.prototype
proto自带的一个属性- 创建对象(初始化对象) p --> person.call(p)
#####原型链继承、构造函数继承、call apply继承
callee 返回正在执行的function对象,function内容
arguments.callee 默认值 正在执行的function对象
- 准则1:小即是美
- 准则2:让每个程序只做好一件事
- 准则3:快速建立原型
- 准则4:舍弃高效率而取可移植性
- 准则5:采用纯文本来存储数据
- 准则6:杠杆效应
- 准则7:使用shell脚本来提高杠杆效应和可移植性
- 准则8:避免强制性的用户界面
- 准则9:让每个程序成为过滤器
- S(single) 单一职责原则
- O(open) 开放封闭原则
- L 李式置换原则
- I(interface) 接口独立原则
- D 依赖导致原则 (依赖于抽象而不依赖于具体)
1、创建型 2、组合型 3、行为型
- 创建型
- 工厂模式
- 单例模式
- 原型模式
- 结构型
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
桥接模式组合模式享元模式
- 行为型
策略模式模板方式模式- 观察者模式
- 迭代器模式
职责连模式命令模式- 状态模式
class Product{
constructor(name) {
this.mame = name
}
}
class Creator() {
create(name) {
return new Product(name)
}
}
$('div') 和 new $('div')有何区别
React的createElement方法
Vue的异步组件
设计原则验证
- 构造函数和创建者分离
public class SingleObject {
private SingleObject () {
}
private SingleObject instance = null
public SingleObject getInstance() {
if (instance == null) {
instance = new SingleObject ()
}
return instance
}
public void login(username, password) {
System.out.println('login')
}
}
class Adaptee{
specificRequest() {
return '德国标准接口'
}
}
class Target {
constructor() {
this.adaptee = new Adaptee()
}
request() {
let info = this.adaptee.specificRequest()
return `${info} -> 转接器 -> 中国标准接口`
}
}
let target = new Target()
target.request()
- 将旧接口和使用者进行分离
- 符合开放封闭原则
- 为对象添加新功能
- 不改变其原有的接口和功能
class Circle {
draw() {
console.log('画一个圆')
}
}
class Decorator {
constructor() {
this.circle = new Circle()
}
draw() {
this.circle.draw()
this.setRedLine()
}
setRedLine() {
console.log('设置红色边框')
}
}
let c1 = new Circle()
c1.draw()
console.log('------')
let c2 = new Decorator()
c2.draw()
使用场景ES7 decorator
// 使用方法
@testDec
class Demo{
}
function testDec(target) {
target.isDec = true
}
console.log(Demo.isDec) // true
// 使用方法2
function testDec(isDecVal) { // 将变量传入
return function (target) { // decorator返回一个函数
target.isDec = isDecVal
}
}
@testDec(false)
class Demo{
}
console.log(Demo.isDec) // false
// 对属性添加readOnly
function readOnly (target, name, descriptor) {
descriptor.writable = false
return descriptor
}
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
getName() {
return `${this.name} and ${this.age}`
}
}
var xiaoming = new Person('xiaoming', '18')
xiaoming.getName()
xiaoming.getName = function () {} // error
// 打印日志
function log(target, name, descriptor) {
let oldValue = descriptor.value
descriptor.value = function () {
console.log('is doing ${name} ', arguments)
return oldValue.call(this, arguments)
}
return descriptor
}
class Math() {
@log
add(a, b) {
return a + b;
}
}
var obj = new Math()
obj.add(1, 2) // is doing add, 1 , 2
- 讲现有对象和装饰器分离,两者独立存在
- 符合开放封闭原则
let star = {
name: 'zhang ming',
age: 25,
phone: 'start 111111'
}
let agent = new Proxy(star, {
get: function (target, key) {
if (key === 'phone') {
return 'agent 222222'
}
if (key === 'price') {
return 'agemt 100K'
}
return target[key]
},
set: function (target, key, val) {
if (key === 'price') {
if (val < 120) {
throw new Error('价格太低')
} else {
target.customPrice = val
}
}
}
})
console.log(agent.name)
console.log(agent.name)
console.log(agent.phone)
console.log(agent.price)
agent.price = 130
console.log(agent.customPrice)
-
适配器模式 vs 代理模式 适配器模式: 提供一个不同的接口(如不同版本的插头) 代理模式:提供一模一样的接口
-
代理模式 vs 装饰器模式 装饰器模式:扩展功能,原有功能不变且可直接使用 代理模式:显示原有功能,但是经过限制或者阉割之后的
- 为子系统中的一组接口提供一个高层接口
- 使用者使用这个高层接口
- 发布&订阅
- 一对多
class Subject{
constructor() {
this.state = 0
this.notifyArr = []
}
setState(state) {
this.state = state
this.notifyAll()
}
getState() {
return this.state
}
notifyAll() {
this.notifyArr.forEach(notify => {
notify.update()
})
}
addNotify(fn) {
this.notify.push(fn)
}
}
class Observer{
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.notifyArr.push(this)
}
update() {
console.log(`${this.name} is notify, state is ${this.subject.getState()}`)
}
}
var sub1 = new Subject()
var o1 = new Observer('o1', sub1)
var o2 = new Observer('o2', sub1)
var o3 = new Observer('o3', sub1)
sub1.setState(1)
sub1.setState(2)
sub1.setState(3)
使用案例:
- JQuery callback
- Nodejs 自定义事件 其他场景
- nodejs处理http请求,多进程通讯
- vue和React组件生命周期触发
- vue watch
// nodejs 自定义事件
const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter()
emitter1.on('some', info => {
console.log('fn1', info)
})
emitter1.on('some', info => {
console.log('fn2', info)
})
emitter1.emit('some', 'message')
设计原则验证
- 主题和观察者分离,不是主动触发而是被动监听,两者解耦
- 符合开放封闭原则
- 顺序访问一个集合
- 使用者无需知道集合的内部结构(封装)
ES6 Iterator为何存在?
- ES6语法中,有序集合的数据类型意见又很多
- Array Map Set String TypedArray arguments NodeList
- 需要有一个统一的遍历接口来遍历所有数据类型
- (注意,object不是有序集合,可以用Map代替)
- 以上数据类型,都有[Symbol,iterator]属性
- 属性值是函数,执行函数返回一个迭代器
- 这个迭代器就有next方法可以顺序迭代子元素
- 可运行Array.protptype[Symbol.iterator]来测试