热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[路飞]每日一答:如何利用闭包和立即执行函数实现类库的封装?

[路飞]每日一答:如何利用闭包和立即执行函数实现类库的封装?-highlight:ascetictheme:channing-cyan如何利用闭包和立即执行函数实现类库的封装

highlight: ascetic
theme: channing-cyan

如何利用闭包和立即执行函数实现类库的封装

封装类库的特点

类库是我们在开发中经常用到的,但是在使用的时候我们很少会考虑他是如何设计的,如何实现封装的。

首先我们要了解类库的特点是什么。类库最基础的要求就是高复用性和低耦合性。这就引申出类库实际上不仅要求脱离业务更要求他有自己的作用域和命名空间。那么利用闭包和立即执行函数就可以做到这一点。

比较一下

第一种写法:

var name = 'defaultName' // 变量 name
function Person () {
  this.name = name // 属性 name 默认为变量 name
}

const p = new Person()
console.log(p) // Person {name: "detaultName"}

这么写功能上固然是没有问题的,我们可以看到返回了一个默认值为 defaultNameperson对象
。但是,如果你尝试去打印 this.name 或者 window.name :

console.log(this.name) // defaultName
console.log(window.name) // defaultName

不难发现,我们全局作用域下的 name属性也受到了影响。

第二种写法

const Person = (function () {
  var name = 'defaultName' // 变量 name
  const Person = function () {
    this.name = name // 属性 name 默认为变量 name
  }
  return Person
})()

const p = new Person()
console.log(p) // Person {name: "detaultName"}
console.log(this.name) // ''
console.log(window.name) // ''

采用了闭包和立即执行函数的形式,为类库的实现创建了单独的作用空间,最终返回一个对象或一个方法的形式。这样一来,类库下的作用域以及变量就不会对全局造成影响,也不会受到命名的限制。

典型案例

大名鼎鼎 jQuery 架构:

;(function(global, factory) { 
    factory(global); 
}(typeof window !== "undefined" ? window : this, function(window, noGlobal) { 
    var jQuery = function( selector, context ) { 
        return new jQuery.fn.init( selector, context ); 
    }; 
    jQuery.fn = jQuery.prototype = {}; 
    // 核心方法 
    // 回调系统 
    // 异步队列 
    // 数据缓存 
    // 队列操作 
    // 选择器引 
    // 属性操作 
    // 节点遍历 
    // 文档处理 
    // 样式操作 
    // 属性操作 
    // 事件体系 
    // AJAX交互 
    // 动画引擎 
    return jQuery; 
})); 

尝试去分解一下。首先是一个自执行函数:

function(global, factory) { factory(global); }

它包含了两个入参,第一个是挂载对象(默认全局),第二个是工厂方法。那么这个自执行对象的传参分别是

typeof window !== "undefined" ? window : this

以及下面的整段方法了

function(window, noGlobal) { 
    var jQuery = function( selector, context ) { 
        return new jQuery.fn.init( selector, context ); 
    }; 
    jQuery.fn = jQuery.prototype = {}; 
    // 核心方法 
    // 回调系统 
    // 异步队列 
    // 数据缓存 
    // 队列操作 
    // 选择器引 
    // 属性操作 
    // 节点遍历 
    // 文档处理 
    // 样式操作 
    // 属性操作 
    // 事件体系 
    // AJAX交互 
    // 动画引擎 
    return jQuery; 
}

如果我们不使用立即执行函数去实现就应该会变成这样:

var window = typeof window !== "undefined" ? window : this
function(window) { 
    var jQuery = function( selector, context ) { 
        return new jQuery.fn.init( selector, context ); 
    }; 
    jQuery.fn = jQuery.prototype = {}; 
    // 核心方法 
    // 回调系统 
    // 异步队列 
    // 数据缓存 
    // 队列操作 
    // 选择器引 
    // 属性操作 
    // 节点遍历 
    // 文档处理 
    // 样式操作 
    // 属性操作 
    // 事件体系 
    // AJAX交互 
    // 动画引擎 
    return jQuery; 
}

由于自身的入参本身就是全局对象window,这种写法可能也不会对全局造成什么影响,但是也太不优雅了。


推荐阅读
  • 本文探讨了在 Vue 2.0 项目中使用 Axios 获取数据时可能出现的错误,并提供详细的解决方案和最佳实践。 ... [详细]
  • 本文介绍如何使用 Angular 6 的 HttpClient 模块来获取 HTTP 响应头,包括代码示例和常见问题的解决方案。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 在 ExtJS 中,类的别名(alias)是开发过程中非常有用的一个特性。通过别名,开发者可以使用简短且易于记忆的名称来引用复杂的类名。本文将详细探讨如何在 ExtJS API 中使用和定义别名,并提供实例说明。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 本文详细介绍了中央电视台电影频道的节目预告,并通过专业工具分析了其加载方式,确保用户能够获取最准确的电视节目信息。 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • JavaScript实现表格数据的实时筛选功能
    本文介绍如何使用JavaScript实现对表格数据的实时筛选,帮助开发者提高用户体验。通过简单的代码示例,展示如何根据用户输入的关键字动态过滤表格内容。 ... [详细]
  • 本文详细介绍了 JavaScript 中类 (class) 的基本语法、定义方式、属性保护方法、私有属性的实现以及继承机制。通过具体的代码示例和详细的解释,帮助开发者更好地掌握 JavaScript 类的相关知识。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 本文介绍如何通过 JavaScript 实现一个基于鼠标坐标的 Tooltip 弹出层,详细解释了如何获取窗口和文档的尺寸及滚动位置,并优化了代码结构。 ... [详细]
  • 探讨了如何解决Ajax请求响应时间过长的问题。本文分析了一个从服务器获取少量数据的Ajax请求,尽管服务器已经对JSON响应进行了缓存,但实际响应时间仍然不稳定。 ... [详细]
  • 在项目部署后,Node.js 进程可能会遇到不可预见的错误并崩溃。为了及时通知开发人员进行问题排查,我们可以利用 nodemailer 插件来发送邮件提醒。本文将详细介绍如何配置和使用 nodemailer 实现这一功能。 ... [详细]
  • 本文详细探讨了JavaScript中的作用域链和闭包机制,解释了它们的工作原理及其在实际编程中的应用。通过具体的代码示例,帮助读者更好地理解和掌握这些概念。 ... [详细]
author-avatar
阡蓝fliona
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有