# 三.单例模式
把描述同一事物(同一个对象)的属性和方法在一个内存空间下,起到了分组的作用,这样不同事物之间的属性即使属性名相同,相互也不会发生冲突,我们把这种分组编写代码的模式叫做"单例模式"
# 1.类图
# 2.代码
var person1 = {
//在单利模式中我们把preson1或者preson2也叫做“命名空间”
name: "yiyi",
age: "17",
}
var person2 = {
name: "wew",
age: "16",
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
//单利模式是一种项目开发中经常使用的模式,因为项目中我们可以使用单利模式来进行“模块化开发”
//“模块化开发”对于一个相对来说比较大的项目,需要多人协作的开发,我们一般情况下会根据当前项目的需求划分成几个功能板块,每个人负责一部分,同事开发,最后把每个人的代码进行合并
//公共模块
var utils = {
select: function() {},
}
//页卡模块中的change-->实现选项卡切换
var tabRender = {
change: function() {
utils.select() //在自己的命名空间下调用其他命名空间的方法
},
}
//搜索模块change ->搜索内容变化处理
var searchRender = {
change: function() {
this.clickEven() //在自己的命名空间下调用自己的方法
},
clickEven: function() {},
}
/* 惰性思想封装 */
//使用惰性思想(js高级编程)
var jsPerson = {
name: "223",
age: "34",
writeJs: function() {
console.log("my name is " + this.name)
},
}
jsPerson.writeJs()
//单例模式虽然解决了分组的作用,但是不能实现批量的生产,属于手工作用模式 -->"工厂模式"
//把实现同一事件的相同代码放到一个函数中,以后如果在想实现这个功能,不需要从新编写这些代码,只需要执行当前的函数即可 -->'函数的封装'
//-->'低耦合高内聚':减少页面中的冗余代码,提高代码的重复利用率
function createJsPerson(name, age) {
var obj = {}
obj.name = name
obj.age = age
obj.writeJs = function() {
console.log("my name is " + this.name)
}
return obj
}
var p1 = createJsPerson("xxx", "47")
//所有的编程语言都是面向对象开发的 -->类的继承、封装、多态
//继承:子类继承父类中的属性和方法
//多态:当前方法的多种形态(后台语言中:多态包含重载和重写)
//js中不存在重载,方法名一样的话,后面的会把前面的覆盖掉,最后只保留一个
//js中有一个操作类似重载但是不是重载:我们可以根据传递参数的不一样的,实现不同的功能
function sum(num) {
if (typeof num === "undefined") {
return 0
}
return num
}
sum(100)
sum()
//重写:子类重写父类的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 2.1 typescript 单例模式
class Window {
name: string
constructor(name: string) {
this.name = name
}
static getInstance(name: string) {
var ins: any = this.instance || null
if (!ins) {
ins = new Window(name)
}
return this.getInstance
}
}
var w1 = Window.getInstance()
var w2 = Window.getInstance()
console.log(w1 === w2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2.2 es5 单例模式
var Window = function(name) {
this.name = name
}
Window.prototype.getName = function() {
console.log(this.name)
}
Window.getInstance = (function() {
var window = null
return function(name) {
if (!window) window = new Window(name)
return window
}
})()
var window = Window.getInstance("123")
window.getName()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2.3 透明单例
let Window = (function() {
let window
let Window = function(name) {
if (window) {
return window
} else {
this.name = name
return (window = this)
}
}
Window.prototype.getName = function() {
console.log(this.name)
}
return Window
})()
let window1 = new Window("123")
let window2 = new Window("123")
window1.getName()
console.log(window1 === window2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.4 单例与构建分离
function Window(name) {
this.name = name
}
Window.prototype.getName = function() {
console.log(this.name)
}
let createSingle = (function() {
let instance
return function(name) {
if (!instance) {
instance = new Window(name)
}
return instance
}
})()
let window1 = new createSingle("123")
let window2 = new createSingle("123")
window1.getName()
console.log(window1 === window2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.5 封装变量
function Window(name) {
this.name = name
}
Window.prototype.getName = function() {
console.log(this.name)
}
let createSingle = function(Constructor) {
let instance
return function() {
if (!instance) {
Constructor.apply(this, arguments)
Object.setPrototypeOf(this.Constructor.prototype)
instance = this
}
return instance
}
}
let CreateSingle = createSingle(Window)
let window1 = new CreateSingle("123")
let window2 = new CreateSingle("123")
window1 = window2
console.log(window1 === window2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 2.6 命名空间
- 用户编写的代码与内部的类/函数/常量或第三方类/函数/常量之间的名字冲突
- 为很长的标识符名称创建一个别名(或简短)的名称,提高源代码的可读性。
jQuery
let $ = {
ajax() {},
get() {},
post() {},
}
1
2
3
4
5
2
3
4
5
let utils = {}
utils.def = function(namespace, fn) {
let _namespace = namespace.split(".")
let fnName = _namespace.pop()
let current = utils
for (let i = 0; i < _namespace.length; i++) {
let __namespace = _namespace[i]
if (!current[__namespace]) {
current[__namespace] = {}
}
current[__namespace][fnName] = fn
}
}
utils.def("dom.attr", function(key) {
console.log("dom.attr")
})
utils.def("dom.html", function(html) {
console.log("dom.html")
})
utils.def("string.trim", function() {
console.log("string.trim")
})
utils.dom.attr("src")
utils.string.trim("aa")
console.dir(utils)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3.场景
# 3.1 jQuery
if (window.jQuery != null) {
return window.jQuery
} else {
// init
}
1
2
3
4
5
2
3
4
5
# 3.2 模态窗口
# 3.3 store
# 3.4 缓存
# 3.5 LRU 缓存
- lru-cache
- 为 LRU Cache 设计一个数据结构,它支持两个操作:
- 1.get(key):如果 key 在 cache 中,则返回对应的 value 值,否则返回-1
- set(key,value):如果 key 不在 cache 中,则将该(key,value)插入 cache 中(注意,如果 cache 已满,则必须把最近最久未使用的元素从 cache 中删除);如果 key 在 cache 中,则重置 value 的值