读《JavaScript设计模式与开发实践》(一)

前言

目前我在开发中也接触了一些js的设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。正好手头有一本书 《JavaScript设计模式与开发实践》 ,所以打算好好研读一下,改变一下面向过程的编码方式。

这本书是由曾探大佬撰写(图灵社区主页)。该系列文章我会根据自己的理解结合最新的相关规范来写,有错误的地方还望社区大佬指正。

前置知识

在开始设计模式学习之前,本书的第一章节主要讲了需要了解的关于js的一些知识。

动态类型语言

编程语言按照数据类型可以分为 静态类型语言动态类型语言

静态类型语言在编译时就已经确定了变量的类型,例如C语言在声明变量时需要指定变量的数据类型,如 int a = 1 ;而动态类型语言则是在程序运行时,通过判断被赋予的值来确定类型,js就是一门典型的动态语言。

js 复制代码
let a;
console.log(typeof a) // undefined
a = 10;
console.log(typeof a) // number
a = 'abc'
console.log(typeof a) // string

相比于静态类型语言,动态类型语言虽然可能会在程序运行时发生类型相关的错误,但是编写的代码更加简洁易懂,同时具有很强的灵活性,这一切建立在 鸭子类型 的概念上。

鸭子类型:如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。

鸭子类型指导我们只关注对象的行为,而不需要关注对象本身。在动态类型语言的面向对象设计中,鸭子类型的概念至关重要,根据鸭子类型,可以总结出一条原则:面向接口编程,而不是面向实现编程。例如如果一个对象拥有push和pop方法与length属性,并可以通过下标存取属性,在某些情况下,就可以当作一个数组来进行使用。

多态

多态的实际含义是同一操作作用于不同的对象上面,可以产生不同的解释与不同的执行结果,通俗来讲就是给不同的对象发送同一个消息得到不同的反馈,多态的核心思想就是将"不变的"和"可变的"分离开。

举个例子:我养了一只猫和一只狗,我对他们下发"叫"的命令,猫会喵喵喵,狗会汪汪汪,在这个例子中,"叫"的命令是不变的,而具体每一只动物的叫声则是可变的,用js代码实现如下:

js 复制代码
const makeSound = function (animal) {
  if (animal instanceof Cat) {
    console.log("喵喵喵");
  } else if (animal instanceof Dog) {
    console.log("汪汪汪");
  }
};

class Cat {}
class Dog {}

makeSound(new Cat()); // 喵喵喵
makeSound(new Dog()); // 汪汪汪

在上述代码中,给CatDog两个类发送了相同的makeSound命令,得到了不同的反馈,但是这一段代码存在一个缺点,就是当我继续增加养的动物时,我需要同步增加makeSound函数中的内容,当动物种类越来越多时,函数也变得越来越臃肿,所以我们需要把不变的部分单独提取出来,以下是优化后的代码:

js 复制代码
const makeSound = function (animal) {
  if (animal.sound instanceof Function) {
    animal.sound(); // "叫"的命令是不变的
  }
};

class Cat {
  sound() {
    console.log("喵喵喵");
  }
}
class Dog {
  sound() {
    console.log("汪汪汪");
  }
}

makeSound(new Cat()); // 喵喵喵
makeSound(new Dog()); // 汪汪汪

这一段代码通俗来讲就是给所有能叫的动物发送"叫"的命令,所以当继续增加动物时,只需要在动物这个类中声明"叫"的动作即可。由此可见,某一动物是否能发出叫声,只取决于动物有没有sound方法,这就是在js这门动态类型语言中,类或者说对象的多态性是与生俱来的。将行为分布在各个对象中,并让这些对象各自负责自己的行为,这正是面向对象设计的优点。

封装

封装的目的主要是为了将一些属性或方法隐藏起来,然后向外提供一些公有方法。通过对对象的封装,对象内部的一些变化对于其他对象而言是透明的,只通过公有方法进行通信,符合"低耦合"原则。

在Java等语言中,提供了public、private等关键字来控制属性的访问权限,但是在js(ES6之前 )中并没有提供这样的关键字,所以我们需要利用到js的一个特性------ 闭包

在红宝书上,闭包的定义如下:闭包是指有权访问另外一个函数作用域中的变量的函数。

所以当我们返回一个函数调用了函数内部变量的时候,此时就产生了闭包,而这个变量也就成为了外部无法访问的私有变量:

js 复制代码
var Obj = function() {
  var _name = "张三"

  return {
    getName: function() {
      return _name
    },
    setName: function(val) {
      _name = val
    }
  }
}

var obj1 = new Obj()

console.log(obj1.getName()); // 张三
obj1.setName("李四")
console.log(obj1.getName()) // 李四
console.log(obj1._name) // undefined

而在ES6中,我们拥有了更多的方法来实现私有属性,我将在另一篇文章中展开细说。

相关推荐
小北方城市网3 分钟前
第 5 课:Vue 3 HTTP 请求与 UI 库实战 —— 从本地数据到前后端交互应用
大数据·前端·人工智能·ai·自然语言处理
踢球的打工仔3 分钟前
ajax的基本使用(上传文件)
前端·javascript·ajax
樊小肆5 分钟前
ollmam+langchain.js实现本地大模型简单记忆对话-内存版
前端·langchain·aigc
徐小夕8 分钟前
pxcharts 多维表格开源!一款专为开发者和数据分析师打造的轻量化智能表格
前端·架构·github
电商API&Tina9 分钟前
跨境电商速卖通(AliExpress)数据采集与 API 接口接入全方案
大数据·开发语言·前端·数据库·人工智能·python
编程乐学(Arfan开发工程师)18 分钟前
信息收集与分析详解:渗透测试的侦察兵 (CISP-PTE 核心技能)
java·开发语言·javascript·python
Mintopia22 分钟前
🏗️ B端架构中的用户归因与埋点最佳实践
前端·react.js·架构
码界奇点23 分钟前
基于Gin+Vue的前后端分离权限管理系统设计与实现
前端·vue.js·车载系统·毕业设计·gin·源代码管理
LYFlied34 分钟前
前端跨端技术全景解析:从本质到未来
前端·职场和发展·跨端
Mintopia35 分钟前
🌐 技术迭代速度与监管适配:WebAIGC的发展平衡术
前端·人工智能·aigc