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 相关文章推荐
关于JavaScript的gzip静态压缩方法
Jan 05 Javascript
jQuery 表格工具集
Apr 25 Javascript
js 字符串转换成数字的三种方法
Mar 23 Javascript
javascript制作的网页侧边弹出框思路及实现代码
May 21 Javascript
javascript字符串与数组转换汇总
May 26 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
Aug 25 Javascript
谈谈JavaScript中浏览器兼容问题的写法小议
Dec 17 Javascript
vuejs响应用户事件(如点击事件)
Mar 14 Javascript
JS中使用gulp实现压缩文件及浏览器热加载功能
Jul 12 Javascript
基于JavaScript 性能优化技巧心得(分享)
Dec 11 Javascript
jquery获取input输入框中的值
Nov 13 jQuery
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
May 19 jQuery
深入学习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
Access数据库导入Mysql的方法之一
2006/10/09 PHP
php网站地图生成类示例
2014/01/13 PHP
双冒号 ::在PHP中的使用情况
2015/11/05 PHP
Yii2框架实现数据库常用操作总结
2017/02/08 PHP
(跨浏览器基础事件/浏览器检测/判断浏览器)经验代码分享
2013/01/24 Javascript
jquery实现图片裁剪思路及实现
2013/08/16 Javascript
JavaScript获取页面中第一个锚定文本的方法
2015/04/03 Javascript
Seajs 简易文档 提供简单、极致的模块化开发体验
2016/04/13 Javascript
用Vue.js实现监听属性的变化
2016/11/17 Javascript
jQuery用FormData实现文件上传的方法
2016/11/21 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
2017/01/19 Javascript
JS中this的指向以及call、apply的作用
2018/05/06 Javascript
LayUi中接口传数据成功,表格不显示数据的解决方法
2018/08/19 Javascript
微信小程序的开发范式BeautyWe.js入门详解
2019/07/10 Javascript
webpack HappyPack实战详解
2019/10/08 Javascript
vue使用better-scroll实现滑动以及左右联动
2020/06/30 Javascript
nuxt 自定义 auth 中间件实现令牌的持久化操作
2020/11/05 Javascript
实用的 vue tags 创建缓存导航的过程实现
2020/12/03 Vue.js
[03:57]2016完美“圣”典风云人物:rOtk专访
2016/12/09 DOTA
[01:03:50]DOTA2-DPC中国联赛 正赛 CDEC vs DLG BO3 第二场 2月7日
2021/03/11 DOTA
Python实现网站注册验证码生成类
2017/06/08 Python
TensorFlow Session使用的两种方法小结
2018/07/30 Python
Python 没有main函数的原因
2020/07/10 Python
python中添加模块导入路径的方法
2021/02/03 Python
HTML5进度条特效
2014/12/18 HTML / CSS
Coggles美国/加拿大:高级国际时装零售商
2018/10/23 全球购物
CK巴西官方网站:Calvin Klein巴西
2019/07/19 全球购物
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
上海某公司.net方向笔试题
2014/09/14 面试题
25道Java面试题集合
2013/05/21 面试题
医校毕业生自我鉴定
2014/01/25 职场文书
水电工程师岗位职责
2015/02/13 职场文书
小学班主任自我评价
2015/03/11 职场文书
保险公司反洗钱宣传活动总结
2015/05/08 职场文书
Python3.10的一些新特性原理分析
2021/09/15 Python
Vue3中toRef与toRefs的区别
2022/03/24 Vue.js