JavaScript世界第一等公民 函数的几个级别

  1. 1.入门级
    在<script></scirpt>标签里写两种函数:
    f1();
    f2();
    function f1(){
    alert("function1");
    }
    var f2 = function(){
    alert("function2");
    }
     
    这两种书写方式是有一点区别的:f1是一种函数命名方式,在初始化window这个顶级对象时候,所有内在的这些函数都已经初始化过了,所以无论在哪个地方调用都是正确的,本质上是属于window的一个属性而存在的;而第二种实质上是一种函数匿名方式存在的,f2是window的一个变量,它指向一个函数表达式,表达式是解释执行的方式,只有运行到这个函数的地方才动态去执行,所以之前f2是没有指向该函数的,但是其值已经有了,是一个undefined,这是由于var这个关键词在初始化全局或局部变量时候,var变量是一次性全部初始化完成的,所以会先有一个值存在。当代码执行到 f2=function..的时候,f2才得到一个函数的指向。此时才能调用。
     
    函数递归:
    斐波那契函数:
    function fib(n){
        if(n==1 || n==2){
                return 1;
        }else{
                return fib(n-2)+fib(n-1);
            }
    }
     
    函数参数匿名:
    函数内部有一个arguments参数可以获取到函数的参数对象,该对象是一个array,
    function test1(){
        para = arguments;
    }
     
    2.进阶 匿名函数和嵌套函数:
    匿名函数由于没有名称调用,而基本上以一次性执行而存在。如:
    (funciton(){}());  (function( ){  })();都是可以直接执行内部函数体的,而里面的环境为一个全新的变量环境不会污染全局环境,带来方便,js执行环境中有一个glob环境,一不小心就会使得各个引入包之间的函数重名,为此,使用匿名函数来处理这个变量重名问题,将所在的js代码全部封装到各自的匿名函数执行环境中,然后暴露出接口,使得全局能访问到内部函数就可以了:
    var mylib=(function(global){
    function log(){
    alert('logs');
    }
                            log1 = log;//1.该方式是利用匿名变量即全局变量,注册到window对象上,不推荐
     
    global.log1 = log;//2.通过函数接口注册到window上,推荐
     
    return {                //3。该方式利用前面mylib的指向得到return的对象,该返回值是一个  、、、、、、、、、对象,对象拥有各种接口访问到匿名函数中的各个函数,相当于一个‘’‘’‘’‘’mylib命名空间下各种资源调用,推荐。
    log:log
    }
    }(window));
     
    高阶函数:当函数作为一个函数的参数使用时,就是高阶函数了
    function plus(n){
    return n+n;
    }
     
    function square(n){
    return n*n;
    }
     
    function fn(n,callback){
    return callback(n);
    };
     
    alert(fn(22,plus));
    alert(fn(22,square));
     
    闭包:
        闭包(Closure)并不是一个新鲜的概念,很多函数式语言中都使用了闭包。在JavaScript中,当你在内嵌函数中使用外部函数作用域内的变量时,就是使用了闭包。用一个常用的类比来解释闭包和类(Class)的关系:类是带函数的数据,闭包是带数据的函数
    闭包中使用的变量有一个特性,就是它们不在父函数返回时释放,而是随着闭包生命周期的结束而结束。比如像上一节中generator的例子,gen1和gen2分别使用了相互独立的变量i(在gen1的i自增1的时候,gen2的i并不受影响,反之亦然),只要gen1或gen2这两个变量没有被JavaScript引擎垃圾回收,他们各自的变量i就不会被释放在JavaScript编程中,不知不觉就会使用到闭包,闭包的这个特性在带来易用的同时,也容易带来类似内存泄露的问题。
     
    1. var elem = document.getElementById('test');  
    2. elem.addEventListener('click'function() {  
    3.   alert('You clicked ' + elem.tagName);  
    4. });  
    5.  
    这段代码的作用是点击一个结点时显示它的标签名称,它把一个匿名函数注册为一个DOM结点的click事件处理函数,函数内引用了一个DOM对象elem,就形成了闭包。这就会产生一个循环引用,即:DOM->闭包->DOM->闭包...DOM对象在闭包释放之前不会被释放;而闭包作为DOM对象的事件处理函数存在,所以在DOM对象释放前闭包不会释放,即使DOM对象在DOM tree中删除,由于这个循环引用的存在,DOM对象和闭包都不会被释放。可以用下面的方法可以避免这种内存泄露:
    上面这段代码中用this代替elem(在DOM事件处理函数中this指针指向DOM元素本身),让JS运行时不再认为这个函数中使用了父类的变量,因此不再形成闭包。
    闭包还会带来很多类似的内存泄露问题,只有在写代码的时候着重注意一下闭包,尽量避免此类的问题产生
     
    函数作为类的构造函数:
    function Person(name){
        this.name = name;
        this.toString = function(){
            return "hello"+this.name +"!";
        }
    }
     
    var p = new Person("ddtou");
    alert(p);
     
    三。妖怪级别:
    1  .Function类。在javascript运行时中有一个内建的类叫做Funciton,用funciton关键字声明一个函数其实就是创建一个Function类的实例的简写方法,因此,所有的函数都拥有Function类的方法如:call,apply,bind。。可以使用instanceof 检查该问题:
     
    既然是对象,那么可以使用原始类生成一个函数对象了:
    new Function ([arg1[, arg2[, ... argN]],] functionBody)  
    前面全是函数参数,最后一个是函数体,需要说明的是函数体使用字符串来传入,所以最外面用"",里面字符串使用'',参数不用加,就能区分是参数还是。。
     
    var f1 = new Function('name',"return 'Hello'+name+'!!'; ");
    f1("ddtou ");//Hello ddtou !!
    到这儿,很多人可能会问为什么需要这样一个妖怪呢?“存在的即是合理的”,Function类有它独特的用途,你可以利用它动态地生成各种函数逻辑,或者代替eval函数的功能,而且能保持当前环境不会被污染*。
     
    2.自更新函数:
    函数在执行之后自己将自己更新成新的代码,这个是利用其绑定到的当前环境的指向更新自己的代码,同时利用的也是脚本的特点,直到运行到该地方才执行,动态性:
    function selfUpdate(){
        this.selfUpdate= function(){
                alert("sencond run");
        }
        alert('first run');
    }
     
     
纸上得来终觉浅,绝知此事要躬行
原文地址:https://www.cnblogs.com/d2ee/p/2608299.html