本篇主要体验JavaScript函数的声明、函数参数以及函数闭包。

□ 函数的声明

※ 声明全局函数

通常这样声明函数:

        function doSth() {
            alert("可以在任何时候调用我");
        }

通过这种方式声明的函数属于Window对象,可以在任何地方调用,即在doSth方法的之前和之后都可以调用。

可以在doSth方法之前调用:

        doSth();
        function doSth() {
            alert("可以在任何时候调用我");
        }

可以在doSth方法之后调用:

        function doSth() {
            alert("可以在任何时候调用我");
        }
        doSth();

※ 把函数赋值给变量

        var doSomething = function() {
            alert("只能在声明我之后再调用");
        };

不可以在doSomething方法之前调用:

        doSomething();
        var doSomething = function() {
            alert("只能在声明我之后再调用");
        };

以上,报"undefined funciton ..."错。

可以在doSomething方法之后调用:

        var doSomething = function() {
            alert("只能在声明我之后再调用");
        };
        doSomething();   

□ 函数参数

※ 即使声明的函数没有参数,也可以在调用时传入参数

        doSth("你好");

        function doSth() {
            alert(arguments[0]);
        }

输出结果:你好

※ arguments.callee属性表示函数引用

        doSth("你好");

        function doSth() {
            alert(arguments.callee);
        }


以上,在函数内部使用arguments.callee属性表示的是函数本身。

※ arguments.callee()方法递归调用函数

        doSth();

        function doSth() {
            alert("你好");
            arguments.callee();
        }

输出结果:不断显示"你好"

□ 函数闭包

※ 闭包的形成

先看下面代码:

        function doSth(val) {
            return function() {
                alert(val);
            };
        }

        var fn = doSth("hello");
        fn();

输出结果:hello

在doSth方法内部返回一个匿名函数,通过fn()执行匿名函数,把doSth方法的参数变量val打印了出来。在这里,doSth方法内部的匿名函数被称作"闭包"。换句话说,我们在内存上创建了一个匿名对象。

※ 闭包的释放

如果在调用fn方法之后,通过fn=null,把fn设置为null,首先匿名函数所占内存被释放,接着,由于变量val不再被引用,val所占内存被释放,最后释放doSth所占内存。

※ 过多的"闭包"会增加内存开销

        function doSth(val) {
            return function() {
                alert(val);
            };
        }

        var fn = doSth("hello");
        var fn2 = doSth("hello2");

        fn();
        fn2();
        fn();

输出结果:依次显示hello, hello2, hello

无论是调用fn方法,还是fn2方法,都会在内存上创建匿名对象,消耗更多的内存。

※ 使用"闭包"创建module

举例:声明一个函数用来创建唯一的ID

        var i = 0;

        function CreateUniqueName() {
            var name = "name" + i;
            i = i + 1;
            return name;
        }

        var name1 = CreateUniqueName();
        var name2 = CreateUniqueName();

        alert(name1 + " " + name2);

输出结果:name0 name1

以上存在几个问题:
1、创建的函数不是全局的,只能在当前页使用
2、变量i和方法CreateUnqiueName都是全局的,这可能会造成与第三方代码的名称冲突

所以,我们应该把以上的逻辑写成全局,并做成一个module,并自定义名称。

       var myUtilty = (function() {
           var i = 0;
           return {
               CreateUniqueName: function() {
                   var name = "name" + i;
                   i = i + 1;
                   return name;
               }
           };
        }());

        var name1 = myUtilty.CreateUniqueName();
        var name2 = myUtilty.CreateUniqueName();

        alert(name1 + " " + name2);

○ (function(){}());被称作是匿名、自触发函数,返回一个json对象,并且只执行一次
○ 正因为匿名、自触发函数只被执行一次,所有全局只有一个myUtitly对象,不会过多消耗内存
○ json对象的键CreateUniqueName对应一个匿名方法  
○ 匿名、自触发函数可以被看作是全局的、唯一的"闭包"

“JavaScript进阶系列”包括:

JavaScript进阶系列01,函数的声明,函数参数,函数闭包

JavaScript进阶系列02,函数作为参数以及在数组中的应用

JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

JavaScript进阶系列06,事件委托

JavaScript进阶系列07,鼠标事件

JavaScript进阶系列01,函数的声明,函数参数,函数闭包的更多相关文章

  1. JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

    本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y) ...

  2. JavaScript进阶系列02,函数作为参数以及在数组中的应用

    有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...

  3. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  4. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  5. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

  6. JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

    本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...

  7. 深入理解javascript作用域系列第三篇——声明提升(hoisting)

    × 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javasc ...

  8. JavaScript学习系列博客_18_JavaScript中的匿名函数

    匿名函数 - 用函数声明的方式创建一个函数时,不加函数名称. function sum(){ console.log("我是函数sum")} - 不加名称,这样写浏览器是会报错的. ...

  9. javascript进阶系列专题:作用域与作用域链

    字面意思,作用域是指变量和函数的作用范围,换言之,作用域决定了变量和函数的可见性和有效时间.javascript作用域是用函数来区分,与其他语言的大括号不同. for (var i=0; i<5 ...

随机推荐

  1. .gitkeep

    看一个开源项目中有个.gitkeep文件,不知道是干嘛用的查询知道 git是不允许提交一个空的目录到版本库上的,可以在空的文件夹里面建立一个.gitkeep文件,然后提交去即可. 其实在git中 .g ...

  2. Demo005 小学四则运算自动生成程序

    目录 小学四则运算自动生成程序 0.传送门 1.题目要求 2.功能实现 2.1 总体设计 2.2 用户欢迎界面 2.3 用户功能界面 2.4 屏幕输出 2.5 文本输出 2.6 获取时间 2.7 用户 ...

  3. springMVC:将controller中数据传递到jsp页面

    1> 将方法的返回值该为ModelAndView在返回时,将数据存储在ModelAndView对象中如: newModelAndView("/WEBINF/jsp/showData.j ...

  4. 【TensorFlow】获取object detection API训练模型的输出坐标

    如下图,谷歌开源的object detection API提供了五种网络结构的fine-tuning训练权重,方便我们针对目标检测的需求进行模型训练,本文详细介绍下导出训练模型后,如何获得目标检测框的 ...

  5. centos 6.8 启动损坏修复实验

    前两天遇到了一个问题,centos必须借助CD的启动才能进入系统,当时想着做个测试,这会儿正好有时间,在VMWare里面试试. 思想是这样的,删除boot里面的文件,然后重启看效果. 具体过程如下: ...

  6. USING NHIBERNATE WITH MySQL

    In previous USING NHIBERNATE WITH SQLITE, we connect SQLITE with ORM framework NHibernate. One of th ...

  7. 二维码生成delphi版

    二维码生成delphi版 生成二维码的软件,代码从C语言转换过来(源地址:http://fukuchi.org/works/qrencode/),断断续续的差不多花了一周时间来转换和调试.在转换过程中 ...

  8. tispark部署步骤

    正常在我们的环境使用tidb集群,都默认没有spark集群的,但之前部署tidb的时候,spark默认已经和系统编译,下面我们的工作就是搭建spark集群和tikv融合 官方是要我们下载tispark ...

  9. EntityFramework 系列:实体类配置-根据依赖配置关系和关联

    EF实体类的配置可以使用数据注释或Fluent API两种方式配置,Fluent API配置的关键在于搞清实体类的依赖关系,按此方法配置,快速高效合理.为了方便理解,我们使用简化的实体A和B以及A.B ...

  10. 【LOJ】 #6012. 「网络流 24 题」分配问题

    题解 又写了一遍KM算法,这题刚好是把最大最小KM拼在一起写的,感觉比较有记录价值 感觉KM始终不熟啊QAQ 算法流程大抵如下,原理就是每次我们通过减少最少的匹配量达成最大匹配,所以获得的一定是最大价 ...