js闭包用法实例详解


Posted in Javascript onDecember 13, 2016

本文实例讲述了js闭包用法。分享给大家供大家参考,具体如下:

引言

在公司中需要写一个js脚本来进行网站的统计,实现类似百度统计或者站长统计的功能,在实现的过程中自己感觉写的代码还是可以的,因为之前的js代码都是这些写,但是在组长代码走查的时候却非常的不满意,因为我们在js中写的方法都是全局的方法,因为我们写的东西需要嵌入到别人的界面中,所以这些全局的东西很可能会和别人的东西重名从而引发错误,所以说组长就给我留下一句话:用js闭包包起来。

变量作用域

我们都非常的熟悉变量的作用域就分为:全局变量和局部变量。js中在函数的内部可以直接读取全局变量。

Js代码

var n=999;
function f1(){
  alert(n);
}
f1(); // 999

另一方面,在函数外部自然无法读取函数内的局部变量。

Js代码

function f1(){
  var n=999;
}
alert(n); // error

我们还需要注意,在js中如果声明变量的时候一定要用var命令,否则实际上声明了一个全局的变量!

function f1(){
  n=999;
}
f1();
alert(n); // 999

如何从外部读取全局变量?

我们需要得到函数内部的全局变量该怎么办呢?。在正常情况下我们是做不到的,要想这么实现我们必须想一些办法——在函数的内部在定义一个函数:

function f1(){
  n=999;
  function f2(){
    alert(n); // 999
  }
}

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是JavaScript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

function f1(){
  n=999;
  function f2(){
    alert(n);
  }
  return f2;
}
var result=f1();
result(); // 999

闭包的概念

在上面的代码中f2函数,就是闭包。各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

下面来分享一下我们在项目中用到的js闭包的写法:

(function () {
  function getPageTitle() {
    return document.title;
  }
  function getBrowerLanguage() {
    var browerLanguage = !navigator.browserLanguage ? navigator.language : navigator.browserLanguage;
    return browerLanguage;
  }
  /**
   * 当前页面地址#后的部分
   */
  function getLastUrl() {
    var url = window.location.hash;
    if (!url) {
      return null;
    }
    else {
      return url.toString().split("#")[1];
    }
  }
  function GetRandomNum() {
    var arr = document.cookie.match(new RegExp("(^| )" + "statisticssCookie=([^;]*)(;|$)"));
    if (arr != null) {
      return arr[2];
    } else {
      var tempRandomNum = guid();
      document.cookie = "statisticssCookie = " + tempRandomNum;
      return tempRandomNum;
    }
  }
  function guid() {
    function S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  }
  function addJs() {
    var url = "http://localhost:10086/tongji/tongji/do?title=" + getPageTitle() + "&browerLanguage=" + getBrowerLanguage() + "&lastUrl=" + getLastUrl() + "&upFlag=" + GetRandomNum();
    var head = document.getElementsByTagName('head')[0];
    var js = document.createElement('script');
    js.type = 'text/javascript';
    js.src = url;
    head.appendChild(js);
  }
  window.statistics = addJs;//将addJs这个方法挂在window下面,这样在外界是可以访问的,否则外界永不能访问到我写的方法
  document.ready = addJs();//DOM树加载完成后执行
})(window)

小结

在开始的时候组长就问我会不会js闭包函数,因为如果不会闭包写不出很好的代码。写的代码都非常的粗糙,所以说我们在写代码的时候,不能仅仅满足功能实现,而且需要考虑一些其他方面的东西。当然js闭包在使用的时候也有一些弊端,所以我们在使用的时候也需要综合全面的信息考虑。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
innertext , insertadjacentelement , insertadjacenthtml , insertadjacenttext 等区别
Jun 29 Javascript
js限制文本框为整数和货币的函数代码
Oct 13 Javascript
JS版的date函数(和PHP的date函数一样)
May 12 Javascript
jQuery元素的隐藏与显示实例
Jan 20 Javascript
Linux下编译安装php libevent扩展实例
Feb 14 Javascript
js判断当前页面用什么浏览器打开的方法
Jan 06 Javascript
最实用的jQuery分页插件
Oct 09 Javascript
Bootstrap 按钮样式与使用代码详解
Dec 09 Javascript
Vue实现表格批量审核功能实例代码
May 28 Javascript
JS字符串和数组如何实现相互转化
Jul 02 Javascript
jQuery实现全选按钮
Jan 01 jQuery
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
Apr 06 Vue.js
深入学习Bootstrap表单
Dec 13 #Javascript
ThinkJS中如何使用MongoDB的CURD操作
Dec 13 #Javascript
Bootstrap Img 图片样式(推荐)
Dec 13 #Javascript
Javascript oop设计模式 面向对象编程简单实例介绍
Dec 13 #Javascript
教大家轻松制作Bootstrap漂亮表格(table)
Dec 13 #Javascript
AngularJS自定义控件实例详解
Dec 13 #Javascript
Node.js中process模块常用的属性和方法
Dec 13 #Javascript
You might like
PHP简单系统数据添加以及数据删除模块源文件下载
2008/06/07 PHP
PHP 开发环境配置(Zend Server安装)
2010/04/28 PHP
php线性表顺序存储实现代码(增删查改)
2012/02/16 PHP
基于Discuz security.inc.php代码的深入分析
2013/06/03 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
PHP实现数组根据某个单元字段排序操作示例
2018/08/01 PHP
laravel Validator ajax返回错误信息的方法
2019/09/29 PHP
面向对象继承实例(a如何继承b问题)(自写)
2013/07/01 Javascript
JS实现简单的二维矩阵乘积运算
2016/01/26 Javascript
JS实现重新加载当前页面或者父页面的几种方法
2016/11/30 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
Vue键盘事件用法总结
2017/04/18 Javascript
深入理解React中何时使用箭头函数
2017/08/23 Javascript
js 中rewrap-ajax.js插件实例代码
2017/10/20 Javascript
vue中锚点的三种方法
2018/07/06 Javascript
JS实现HTML页面中动态显示当前时间完整示例
2018/07/30 Javascript
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
2018/09/13 Javascript
vue-cli 使用vue-bus来全局控制的实例讲解
2018/09/15 Javascript
javascript中可能用得到的全部的排序算法
2020/03/05 Javascript
微信小程序用canvas画图并分享
2020/03/09 Javascript
JavaScript文档加载模式以及元素获取
2020/07/28 Javascript
python的tkinter布局之简单的聊天窗口实现方法
2014/09/03 Python
Python编程之gui程序实现简单文件浏览器代码
2017/12/08 Python
Pandas统计重复的列里面的值方法
2019/01/30 Python
python快排算法详解
2019/03/04 Python
Python Django2.0集成Celery4.1教程
2019/11/19 Python
python使用selenium爬虫知乎的方法示例
2020/10/28 Python
建筑毕业生自我鉴定
2013/10/18 职场文书
教导主任竞聘演讲稿
2014/05/16 职场文书
公司副总经理岗位职责
2014/10/01 职场文书
2014五年级班主任工作总结
2014/12/05 职场文书
先进学校事迹材料
2014/12/30 职场文书
2015年话务员工作总结
2015/04/29 职场文书
青年志愿者服务活动总结
2015/05/06 职场文书
Python合并多张图片成PDF
2021/06/09 Python