一、this易错分析

在学习闭包的时候,有一个概念this很重要,关于this的理解,下面3种情况:this指向谁?

fn.call(obj1);
obj2.fn()
fn()

答案是obj1 obj2 window

判断this的指向有3条规则:

执行函数的过程中肯定存在两方,一方是调用函数的人caller,一方是被调用的人callee,callee永远是函数fn,caller遵循以下的规范:

  • fn.call(xxx) fn.apply(xxx)的时候,this永远指向xxx
  • ooo.fn()或者ooo['fn']()的时候,this永远指向ooo
  • fn()的时候this指向window

    所以针对上面代码:
  1. call/apply的作用是改变函数的调用者,或者说是改成this,改变this为 call /apply的第一个参数

  2. 一个函数没人调用的时候,相当于window调用了他

  3. 函数中除去this和arguments的其它变量,均遵守闭包规则,闭包的位置永远是函数定义的位置。

二、闭包易错代码分析

下面看两个代码实例,它们来源于阮一峰的文章闭包讲解。

 var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());

返回结果是:

the window

分析:

alert(object.getNameFunc()());

这个里面有2个括号,要分析两次,把语句拆开:

第一步:var fn = object.getNameFunc();这时执行getNameFunc的时候,this是object,第一次return返回:function(){return this.name;}

第二步fn(),这时候函数由于没有调用者,根据规则3,函数的this ->window,这个函数里面的this.name实际上是window.name


 var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc());
返回结果:My Object

分析

同样分成两步执行:

第一步执行:var fn = object.getNameFunc();这个时候,this指向object,同时在函数执行的过程中,在getNameFunc所在的闭包内创建了变量that,that = this 所以that指向object,然后第二步执行fn(),这个时候由于没有作用对象,fn里面的this指向window,但是我们在这访问的是that.name,在fn里面没有找到叫that的东西,然后根据闭包规则找到fn的上一级闭包getNameFunc,我们发现在这有一个变量that,它指向object,所以that,name就是object.name,是my object

由此可见,闭包的概念更好理解了:

  1. 闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。
  2. 闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配
  3. 当在一个函数内定义另外一个函数就会产生闭包

简单来说,闭包就是在另一个作用域中保存了一份它从上一级函数或作用域取得的变量(键值对),而这些键值对是不会随上一级函数的执行完成而销毁。周爱民说得更清楚,闭包就是“属性表”,闭包就是一个数据块,闭包就是一个存放着“Name=Value”的对照表。就这么简单。但是,必须强调,闭包是一个运行期概念。有两个主要特点:

  • 作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
  • 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

三、闭包的作用

  1. 可以读取函数内部的变量
  2. 让这些变量的值始终保持在内存中。

四、闭包的缺点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

参考资料:

学习Javascript闭包:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

javascript的闭包:http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1530074.html

JavaScript 闭包深入理解:http://www.jb51.net/article/18303.htm

理解 Javascript 的闭包:http://www.oschina.net/question/28_41112

ife task0003学习笔记(三):JavaScript闭包的更多相关文章

  1. ife task0003学习笔记(一):JavaScript作用域

    在学习JavaScript作用域概念之前,首先要明白几个概念:执行环境.变量对象.作用域链. 一.JavaScript执行环境(execution context): 在<Professiona ...

  2. ife task0003学习笔记(五):JavaScript面向对象

    JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.在 Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.而在 JavaScript 中,this ...

  3. ife task0003学习笔记(四):JavaScript构造函数

    JavaScript创建对象主要是3种方法:工厂模式.构造函数模式.原型模式.其实对于构造函数的概念,我们并不陌生.在之前学习c++语言的时候,也有提到过构造函数的概念.除了创建对象,构造函数(con ...

  4. ife task0003学习笔记(二):JavaScript原型

    function aaa(){} aaa.prototype.bbb=function(){} var obj1=new aaa() var obj2=new aaa() obj1和obj2都有一个属 ...

  5. 【学习笔记】JavaScript的基础学习

    [学习笔记]JavaScript的基础学习 一 变量 1 变量命名规则 Camel 标记法 首字母是小写的,接下来的字母都以大写字符开头.例如: var myTestValue = 0, mySeco ...

  6. amazeui学习笔记三(你来我往1)--常见问题FAQs

    amazeui学习笔记三(你来我往1)--常见问题FAQs 一.总结 1.DOM事件失败:记得加上初始化代码,例如 图片轮播 $('#my-slider').flexslider(); 2.jquer ...

  7. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  8. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

  9. RX学习笔记:JavaScript数组操作

    RX学习笔记:JavaScript数组操作 2016-07-03 增删元素 unshift() 在数组开关添加元素 array.unshift("value"); array.un ...

随机推荐

  1. HTML5+CSS3从入门到精通随书光盘 ISO 镜像视频教程​

    HTML5+CSS3从入门到精通(清华社“视频大讲堂”大系)通过基础知识+中小实例+综合案例的方式,讲述了用HTML5+ CSS3设计构建网站的必备知识,相对于权威指南.高级程序设计.开发指南同类图书 ...

  2. Canvas保存为图片

    public static void GenerateCanvas(string imgSaveName, int canvasWidth, int canvasHeight, string imgD ...

  3. 前端框架 json 返回值

    layui: string strJson = "{\"code\": \"0\",\"msg\": \"\" ...

  4. Day3作业 .

    ,))::])]): :-])# 3,使用while和for循环分别打印字符串s=’asdfer’中每个元素. # 4,实现一个整数加法计算器:# 如:content = input(‘请输入内容:’ ...

  5. opencv3.3.1+vs2015+c++实现直接在图像上画掩码,保存掩码图片

    左键红右键蓝,保存为k #include "opencv2\imgproc\imgproc.hpp" // Gaussian Blur #include "opencv2 ...

  6. Atcoder Grand Contest 031B(DP,思维)

    #include<bits/stdc++.h>using namespace std;int a[200007];int b[200007];long long dp[200007];lo ...

  7. windows如何通过端口查看对应程序

    今天打开SSR报错,说端口被占用. 打开的软件有点多,又不想重启.就需要找到占用的软件,关闭了即可. 打开cmd,输入netstat -aon能看到所有的使用端口 其中1080端口是预留给SSR使用的 ...

  8. 【ARC074F】Lotus Leaves 最小割

    Description 给你一个n*m网格图,有起点荷叶和终点荷叶,有中转荷叶,其他的格子没东西,一个荷叶可以跳到同一行或者列的另一个荷叶.问最多删掉几个中转荷叶能让起点终点不连通.如果不行输出-1. ...

  9. [Swift实际操作]八、实用进阶-(10)使用Swift创建一个二叉树BinaryTreeNode

    1.二叉树的特点: (1).每个节点最多有两个子树(2).左子树和右子树是有顺序的,次序不能颠倒(3).即使某节点只有一个子树,也要区分左右子树 2.二叉查找树(Binary Search Tree) ...

  10. 品味ZooKeeper之Watcher机制_2

    品味ZooKeeper之Watcher机制 本文思维导图如下: 前言 Watcher机制是zookeeper最重要三大特性数据节点Znode+Watcher机制+ACL权限控制中的其中一个,它是zk很 ...