《JavaScript设计模式与开发实践》是由曾探所著的一本经典技术书籍。该书详细介绍了JavaScript中常用的设计模式,并结合实际项目开发经验给出了实践示例和最佳实践建议。这本书首先介绍了设计模式的基本概念和作用,以及为什么要在JavaScript中使用设计模式。接着,书中详细介绍了23种常见的设计模式,如单例模式、工厂模式、适配器模式、观察者模式等。每种设计模式都详细解释了其定义、结构、应用场景和优缺点,并给出了实际的代码示例和案例分析。除了介绍设计模式的理论知识,该书还提供了大量的实践经验和开发技巧。其中包括如何组织和管理JavaScript代码、如何优化性能、如何进行模块化开发、如何进行异步编程等方面的内容。这些实践经验有助于读者更好地理解和应用设计模式,提高JavaScript项目的质量和可维护性。《JavaScript设计模式与开发实践》这本书语言简洁明了,通俗易懂,适合初学者入门和有一定经验的开发者进阶学习。通过学习这本书,读者可以深入理解JavaScript设计模式的原理和思想,并能够灵活运用到实际项目中,提高自己的编程水平和软件开发能力。
一、前言:
⭕前置问题:
- 什么是模式?
- 设计模式的适用性是什么?
📜从一个故事开始
- 足球运动包含很多的策略,有一个叫做“下底传中”——用一个名词来去描述一种“战术”,这就是一种“模式”。
- 模式:通过一个特有的名词,来描述一类问题对应的解决方案
✍🏻设计模式的适用性
- 不要有了锤子,看什么都像钉子
- 模式只有放到具体的环境下才有意义
二、 基础知识
1.面向对象的 JavaScript
(1)程序语言设计风格
- 命令式语言(过程化语言)
- 结构化语言
- 面向对象语言 (OOP)
- 函数式语言
- 脚本语言
(2)JavaScript 的语言特性
通过(脚本)原型来实现面向对象的开发(不是标准的面向对象的编程语言)
动态类型语言
概念:变量类型由值确定
let t = 'str' // string 类型
t = 007 // number 类型
🌟鸭子类型:
“从前在JavaScript王国里,有一个国王,他觉得世界上最美妙的声音就是鸭子的叫声,于是国王召集大臣,要组建一个1000只鸭子组成的合唱团。大臣们找遍了全国,终于找到999只鸭子,但是始终还差一只,最后大臣发现有一只非常特别的鸡,它的叫声跟鸭子一模一样,于是这只鸡就成为了合唱团的最后一员。”
var duck = {
duckSinging: function(){
console.log('嘎嘎嘎');
}
};
var chicken = {
duckSinging: function(){
console.log('嘎嘎嘎')
}
var choir =[]; //合唱团
var joinChoir = function(animal ){
if ( animal && typeof animal.duckSinging === 'function' ){
choir.push( animal );
console.log('恭喜加入合唱团' );
console.1og('合唱团已有成员数量:' + choir.length );
}
};
joinChoir( duck );// 恭喜加入合唱团
joinChoir( chicken );// 恭喜加入合唱团
如果有一个动物,走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子。
(3)JavaScript 的多态性
⭕动态类型语言天生具备多态性。
多态:同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。
代码:
var makeSound =function( animal ){
if ( animal instanceof Duck ){
console.log('嘎嘎嘎');
}else if ( animal instanceof Chicken ){
console.log('咯咯咯');
}
};
var Ducka = function(){};
var Chicken = function()[};
makeSound(new Duck() ); //嘎嘎嘎
makeSound(new Chicken() );//咯咯咯
多态背后的思想是将“做什么”和“谁去做以及怎样去做”分离开来,也就是将“不变的事物”与“可能改变的事物”分离开来
2.this、call 和 apply
(1)this 指向问题
- 构造函数:指向实例对象
- 普通函数:指向函数调用方
- 箭头函数:不修改 this 指向,沿用上层作用域的 this
- call、apply、bind:仅作用于普通函数,this 指向第一个参数
(2)this“丢失”
var obj = {
myName: 'sven',
getName: function(){
return this.myName;
}
};
console.log( obj.getName() ); // 输出: sven
//getName是obj下面的方法,this 会指向obj 本身
var getName2 = obj.getName;
//vr声明了一个新的变量的时候 被绑定到windows下面的
console.log( getName2() ); //相对应 window.getName2
//输出:undefined
普通函数调用方式,this 是指向全局window 的
3.闭包和高阶函数
(1)闭包
定义:能够访问其他函数作用域中变量的函数
变量的生存周期:var 声明的变量在非函数作用域下是全局变量
<html>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<script>
var nodes = document.getElementsByTagName( 'div' );
for( var i = 0,len = nodes.length; i < len; i++ ){
nodes[ i ].onclick = function(){
alert ( i );//永远输出5
}
};
</script>
</body>
</html>
闭包解决生存周期问题:
for( var i = 0,len = nodes.length; i < len; i++ ){
(function( i ){
nodes[ i ].onclick = function(){
console.log(i);
}
})( i )
};
⭕注意:ES6之后 let 也可以解决这个问题 (块级作用域)
(2)高阶函数
满足两个条件:
- 函数可以作为参数被传递
- 函数可以作为返回值输出
三、设计模式