前端设计模式

5次阅读

共计 3590 个字符,预计需要花费 9 分钟才能阅读完成。

1、模块模式在立即执行函数表达式中定义的变量和方法,在该函数外部是访问不到的,只能通过该函数提供的接口,” 有限制的 ” 进行访问;通过函数的作用域,解决了属性和方法的封装问题。最常见的立即执行函数写法有以下两种:
(function(){/* code */}())
或者
(function(){/* code */})()
模块模式代码:
let Person = (function(){
var age = “12”;
var name = “jerry”;
function getAge(){
return age;
}
function getName(){
return name;
}
return {
getAge: getAge,
getName: getName
}
})()
console.log(age, ‘age’); // 报错: Uncaught ReferenceError: age is not defined
console.log(name, ‘name’); // 空字符串,为啥不报错?看底部备注
console.log(Person.age); // undefined
console.log(Person.name); // undefined
// 只能通过 Person 提供的接口访问相应的变量
console.log(Person.getName()); // jerry
console.log(Person.getAge()); // 12
2、构造函数模式
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.printName = function(){
console.log(this.name)
}
Person.prototype.printAge = function(){
console.log(this.age)
}
function Student(name,age){
// 继承 Person 的属性
Person.call(this,name,age)
}
function create(prototype){
function F(){}
F.prototype = prototype
return new F()
}
// 让 Student 的原型指向一个对象, 该对象的原型指向了 Person.prototype, 通过这种方式继承 Person 的方法
Student.prototype = create(Person.prototype)
Student.prototype.printAge = function(){
console.log(this.age)
}
let student = new Student(‘jerry’,12)
student.printName() // “jerry”
student.printAge() // “12”
3、混合模式
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.printName = function(){
console.log(this.name)
}
function Student(name,age){
// 继承 Person 的属性
Person.call(this, name, age)
}
function create(prototype){
function F(){}
F.prototype = prototype
return new F()
}
// 让 Student 的原型指向一个对象, 该对象的原型指向了 Person.prototype, 通过这种方式继承 Person 的方法
Student.prototype = create(Person.prototype)
Student.prototype.printAge = function(){
console.log(this.age)
}
let student = new Student(‘jerry’, 12)
student.printName() // “jerry”
student.printAge() // 12
4、工厂模式
function Person(name, age){
let person = new Object()
person.name = name
person.age = age
person.printName = function(){
console.log(this.name)
}
person.printAge = function(){
console.log(this.age)
}
return person
}
let person = Person(‘jerry’,12)
person.printName()
person.printAge()
5、单例模式
let Singleton = (function(){
let instantiated
function init(){
/* 定义单例代码 */
return{
publicMethod: function(){
console.log(“Hello World”);
},
publicProperty: “Test”
}
}
return{
getInstance: function(){
if(!instantiated){
instantiated = init()
}
return instantiated
}
}
}())
Singleton.getInstance().publicMethod()
单例之间的通讯:建立两个独立的对象:jim&&lily,两者之间通过 door 直接通讯,如果没有新建 door,有直接通讯。代码如下:
let jim = (function(argument){
let door
let jimHome = function(msg){
this.doorbell = msg
}
let info = {
sendMessage: function(msg){
if(!door){
door = new jimHome(msg)
}
return door
},
coming: function(){
return “ 來了來了 ”
}
}
return info
}())
let lily = {
callJim: function(msg){
let _xw = jim.sendMessage(msg)
alert(_xw.doorbell)
console.log(_xw.doorbell)
_xw = null // 等待垃圾回收
let coming = jim.coming()
console.log(coming)
}
}
lily.callJim(“ 叮咙 ”)
6、发布 - 订阅模式订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身主题变化时,会通知所有订阅者对象,使他们能够自动更新自己的状态。将一个系统分割成一系列相互协作的类有一个很不好的副作用:需要维护相应对象间的一致性,这样会给维护、扩展和重用都带来不便。当一个对象的改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变时,此时建议使用订阅发布模式。应用场景:DOM 事件。DOM 事件是一种典型的发布 - 订阅模式,对一个 DOM 节点的 DOM 事件进行监听;当操作 DOM 节点时,触发相应的事件并执行函数。自定义时间。指定发布者,类似于一个对象 (key:value);key 表示事件的名称,value 是一个数组;发布消息后,遍历 value 的数组,依次执行订阅者的回调函数。应用 Demo 如下:
let Event = (function(){
var events = {}
function on(evt, handler){
events[evt] = events[evt]||[];
events[evt].push({
handler:handler
})
}
function fire(evt,args){
if(!events[evt]){
return
}
for(var i=0;i<events[evt].length;i++){
events[evt][i].handler(args)
}
}
function off(evt){
delete events[evt]
}
return {
on: on,
fire: fire,
off: off
}
}())
Event.on(‘change’, function(val){
console.log(‘change 事件,value is’ + val)
})
Event.on(‘click’, function(val){
console.log(‘click 事件,value is ‘+ val)
})
Event.fire(‘change’, ‘jerry1’)
Event.fire(‘click’, ‘jerry2’)
Event.off(‘change’)
备注:console.log(name, ‘name’) 没有报错,原因在于 name 是浏览器的窗口变量名,已存在于浏览器内部。

正文完
 0

前端设计模式

5次阅读

共计 898 个字符,预计需要花费 3 分钟才能阅读完成。

作为一个前端新人,学习了设计模式以后,希望能从源头上,用浅显易懂的语言来解释它。当然不一定是正确的,只是我个人对设计模式的一点浅显理解。
创建型设计模式
创建型设计模式:故名思意,这些模式都是用来创建实例对象的。
单例模式
首先我们需要理解什么是单例。单:指的是一个。例:指的是创建的实例。单例:指的是创建的总是同一个实例。也就是使用类创建的实例始终是相同的。我们先看下面的一段代码:

class Person{
constructor(){}
}
let p1 = new Person();
let p2 = new Person();
console.log(p1===p2) //false
上面这段代码,定义了一个 Person 类,通过这个类创建了两个实例,我们可以看到最终这两个实例是不相等的。也就是说,通过同一个类得到的实例不是同一个 (这本就是理所应当),但是如果我们想始终得到的是同一个实例,那么这就是单例模式。那么应该如何实现单例模式了:想要实现单例模式,我们需要注意两点:

需要使用 return。使用 new 的时候如果没有手动设置 return, 那么会默认返回 this。但是,我们这里要使得每次返回的实例相同,也就是需要手动控制创建的对象,因此这里需要使用 return。
我们需要每次 return 的是同一个对象。也就是说实际上在第一次实例的时候,需要把这个实例保存起来。再下一个实例的时候,直接 return 这个保存的实例。因此,这里需要用到闭包了。

代码实现如下:
(function(){
let instance = null;
return class{
constructor(){
if(!instance){
// 第一次创建实例,那么需要把实例保存
instance = this;
}else{
return instance;
}
}
}
})()

let p3= new Person();
let p4 = new Person();
console.log(p3===p4) //true

从上面的代码中,我们可以看到在闭包中,使用 instance 变量来保存创建的实例,每次返回的都是第一次创建的实例。这样的话就实现了无论创建多少次,创建的都是同一个实例,这就是单例模式。

正文完
 0