1.作为命名空间的函数
有时候我们需要声明很多变量。这样的变量会污染全局变量并且可能与别人声明的变量产生冲突。
这时。解决办法是将代码放入一个函数中,然后调用这个函数。这样全局变量就变成了
局部变量。
如:
function my(){

}
my(); //别忘记调用
这段代码定义了一个单独的全局变量:名叫"my"的函数。
我们还可以这么写,定义一个匿名函数:
(function(){       //这里第一个左括号是必须的,如果不写,JavaScript解析器会将
//function解析成函数声明语句,使用的话解析成函数定义表达式 }()) //这里的()的作用是,函数定义完毕后立即调用它。
 
2.闭包
理解一(某书):
函数的执行依赖于变量作用域。为了实现这种词法作用域,必须引用当前的作用域链。
函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,
这种特性在计算机科学中称为“闭包”。
从技术角度上讲,所有的JavaScript函数都是闭包:他们都是对象,他们都关联到作用域链。
调用函数时闭包所指向的作用域链和定义函数时的作用域链不是同一个作用域链时,事情就变得非常微妙。
 
理解二(某书):
闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包的常见方式:就是在一个函数内部创建另一个函数。
 
这里照搬书上的解释:
函数被调用的时候会发生什么?
当函数被调用的时候,会创建一个执行环境和作用域链然后使用参数来初始化函数的活动对象。在作用域链中,外部函数的活动对象始终处于第二位。
 
一般来讲,当函数执行完毕后,局部活动对象(我理解为局部变量)就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
作用域链的作用是保证对执行环境的所有变量和函数的访问。
但是在闭包中情况则不同!
内部函数会将外部函数的活动对象添加到它的作用域链中。在匿名函数从外部函数被返回后,它的作用域链被初始化为包含外部函数的活动对象和全局变量的对象。
 
这样匿名函数就可访问外部函数中定义的所有变量。当外部函数执行完毕后,其活动对象也不会被销毁。因为匿名函数的作用域链仍然在引用这个活动对象。也就是外部函数的作用域链会被销毁,但是他的活动对象仍然会留在内存中。直到匿名函数被销毁后,外部函数的活动对象才会被销毁。
 
(闭包这玩意儿有点麻烦- -,这里不敢举例子来混乱大家的思维,即使是这书上的例子我觉得也不怎么能很好的解释闭包,大家可以查查资料,有自己的理解)
 
2015-10-21 20:01:52 start (对闭包的进一步的个人理解)
闭包指的是一个函数可以访问另外一个函数作用域中的变量。
下面是猜想:
function a(){
  var a1=2;
}
function b(){
  var b1=3;
}
按照上面的定义理解就是:怎么才能让a()函数去访问b()函数中的变量b1?
继续猜想:
我们想到:只要把a()函数放在b()函数中不就可以了么?
实现的原理:a()函数会将b()函数的活动对象添加到它的作用域中。所以a()函数的作用域链包括b()函数的作用域链。
do it!
function b(){
  var b1=3;
  function a(){
    var a1=2;
    alert(b1);
  }
  a();
}
b();  //结果=>3

这样就实现了?然并卵啊!闭包的现实意义在哪?当然“真正”有意义的闭包并不是这样。

闭包的作用:外部函数可以读取函数内部的变量。

      另一个就是让这些变量的值始终保持在内存中。

 
现在我们来说明第一个:外部函数可以读取函数内部的变量。
<1>如果我们都像上面那样写a()函数,那a()函数的作用是不是太狭窄了点,当访问一个内部变量结束后就没用了。是不是有点浪费,如果能在全局对象中去访问一个函数中的内部变量岂不是更酷?!
于是我们可以这样写:
function b(){
var b1=3;
return function (z){
var a1=2;
return alert(b1+z);
}
}
var a=b();
a(2); //=>5

这样我们就在全局作用域中调用了b1这个内部变量。(个人理解,如果有误还请指教。)

匿名函数被返回后,它的作用域链被初始化为包含b()函数的活动对象和全局变量对象。这样匿名函数就可以访问b()中的所有变量。

现在我们来说明第二个:变量的值始终保持在内存中。
<2>在上面例子中。在b()函数执行完毕后,其活动对象不会被销毁!因为匿名函数的作用域链仍然在引用这个活动对象。换句话说,当b()函数返回后,其执行环境中的作用域链会被销毁,但它的活动对象仍然留在内存中。直到匿名函数被销毁,b()函数的活动对象才会被销毁。
必须这样显示的指定:
a=null;
以便释放内存。
 
2015-10-21 20:55:52 end
 
 
 
 
3.闭包与变量:
作用域链的这种配置机制引出一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包保存的是整个变量对象,而不是某个特殊的变量。
function ca(){
var arry=[]; for(var i=0;i<10;i++){
arry[i]=function(){
return i;
}
}
return arry;
}
 
上面这个例子,与我们想要的结果不一样。每个都是返回10。因为每个函数的作用域链中都保存着擦ca()函数的活动对象,所以他们引用的都是同一个函数变量i。
当ca()返回后,变量i的值都是10。这时我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。
 
尝试解决一下:
function ca(){
var arry=[];
for(var i=0;i<10;i++){
arry[i]=function(num){
return function(){
return num;
}
}
}
return console.log(arry);
}
ca();

上面强制闭包错误!返回的都是function(num){}。

下面提供正确的方式:

//第一种方式
function ca(){
var arry=[];
for(var i=0;i<10;i++){
arry[i]=(function(i){
return i;
})(i);
}
return console.log(arry[5]);;
}
ca();
//->5
//第二种方式
function ca(){
var arry=[];
for(var i=0;i<10;i++){
arry[i]=function(){
var n=i;
return n;
}();
}
return console.log(arry[8]);
}
ca();
//->5

我们没有直接把闭包函数赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。

这两种方式都能得到自己想要的结果。

这里在举个实际中的例子:

<!doctype html>
<title></title>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function(){ //方法一
var lists = document.getElementsByTagName("li");
for(var i=0,l=lists.length; i < l; i++){
lists[i].onclick=(function(i){// 强制闭包
return function(){
alert(i)
}
})(i)
}   //方法二
var lists = document.getElementsByTagName("li");
for(var i=0,l=lists.length; i < l; i++){
lists[i].onclick=function(){
var n=i;
return function(){
alert(n)
}
}()
}
  
}
</script>
<ul>
<li id="a1">aa</li>
<li id="a2">aa</li>
<li id="a3">aa</li>
</ul>
 
 
4.Fuction()构造函数
函数可以通过function()构造函数来定义:
var f=new Fuction("x","y","return x*y;");
//->等价于
var f=function(x,y){
return x*y
}

5.constructor属性

每个JavaScript函数都自动拥有一个prototype属性。这个属性的值是一个对象,这个对象包含唯一一个不可枚举属性constructor。constructor属性的值是一个函数对象。
先看代码:
var F=function(){}    //这是一个函数对象
var p=F.prototype; //这是F相关联的原型对象
var c=p.constructor; //true
c===F //对于任意函数F.prototype.constructor==F
 
可以看到构造函数的原型中预先定义好的constructor属性,这意味着对象通常继承的constructor均指代他们的构造函数。由于构造函数是类的"公共标识"因此这个constructor属性为对象提供了类。
 
var o=new F();    //创建类F的一个对象
o.constructor===F //true,constructor属性指代这个类

6.多catch从句

在JavaScript 1.5中,try/catch可以使用多catch从句
如:
try{
//这里肯呢个会抛出多种类型异常
throw 1;
}
catch(e if e instanceof ReferenceError){
//这里处理引用错误
}
catch(e if e==="quit"){
//这里处理抛出的字符串是"quit"的情况
}
catch(e if typeof e==="string"){
//处理其他字符串的情况
}
catch(e){
//处理剩下的异常
}
finally{
//finally从句正常执行
}

--Log----------------------------------------------------------------------------------------------

2015-10-21    添加操作    闭包

 

JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)的更多相关文章

  1. JavaScript权威设计--跨域,XMLHttpRequest(简要学习笔记十九)

    1.跨域指的是什么? URL 说明 是否允许通信 http://www.a.com/a.jshttp://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a. ...

  2. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  3. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  4. JavaScript权威设计--JavaScript函数(简要学习笔记十)

    1.函数命名规范 函数命名通常以动词为前缀的词组.通常第一个字符小写.当包含多个单词时,一种约定是将单词以下划线分割,就像"like_Zqz()". 还有一种就是"lik ...

  5. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  6. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  7. Python学习笔记(十二)—Python3中pip包管理工具的安装【转】

    本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...

  8. JavaScript权威设计--Window对象之Iframe(简要学习笔记十四)

    1.Window对象属性的文档元素(id) 如果在HTML文档中用id属性来为元素命名,并且如果Window对象没有此名字的属性,Window对象会赋予一个属性,它的名字是id属性的值,而他们的值指向 ...

  9. JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)

    1.事件冒泡与事件捕获 2.事件与事件句柄   3.事件委托:利用事件的冒泡技术.子元素的事件最终会冒泡到父元素直到跟节点.事件监听会分析从子元素冒泡上来的事件. 事件委托的好处:     1.每个函 ...

随机推荐

  1. 避免重复造轮子的UI自动化测试框架开发

    一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...

  2. 浅谈 jQuery 核心架构设计

    jQuery对于大家而言并不陌生,因此关于它是什么以及它的作用,在这里我就不多言了,而本篇文章的目的是想通过对源码简单的分析来讨论 jQuery 的核心架构设计,以及jQuery 是如何利用javas ...

  3. .NET Core 首例 Office 开源跨平台组件(NPOI Core)

    前言 最近项目中,需要使用到 Excel 导出,找了一圈发现没有适用于 .NET Core的,不依赖Office和操作系统限制的 Office 组件,于是萌生了把 NPOI 适配并移植到 .NET C ...

  4. Mysql存储引擎及选择方法

    0x00 Mysql数据库常用存储引擎 Mysql数据库是一款开源的数据库,支持多种存储引擎的选择,比如目前最常用的存储引擎有:MyISAM,InnoDB,Memory等. MyISAM存储引擎 My ...

  5. AFNetworking 3.0 源码解读(八)之 AFImageDownloader

    AFImageDownloader 这个类对写DownloadManager有很大的借鉴意义.在平时的开发中,当我们使用UIImageView加载一个网络上的图片时,其原理就是把图片下载下来,然后再赋 ...

  6. 代码的坏味道(16)——纯稚的数据类(Data Class)

    坏味道--纯稚的数据类(Data Class) 特征 纯稚的数据类(Data Class) 指的是只包含字段和访问它们的getter和setter函数的类.这些仅仅是供其他类使用的数据容器.这些类不包 ...

  7. 编译器开发系列--Ocelot语言7.中间代码

    Ocelot的中间代码是仿照国外编译器相关图书Modern Compiler Implementation 中所使用的名为Tree 的中间代码设计的.顾名思义,Tree 是一种树形结构,其特征是简单, ...

  8. 让你从零开始学会写爬虫的5个教程(Python)

    写爬虫总是非常吸引IT学习者,毕竟光听起来就很酷炫极客,我也知道很多人学完基础知识之后,第一个项目开发就是自己写一个爬虫玩玩. 其实懂了之后,写个爬虫脚本是很简单的,但是对于新手来说却并不是那么容易. ...

  9. 如何利用mono把.net windows service程序迁移到linux上

    How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上 ...

  10. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...