JavaScript入门-函数function(二)

JavaScript入门-函数function(二)

递归函数

  • 什么是递归函数?
    递归简单理解就是,在函数体里,调用本身。
//咱们在求一个10的阶乘的时候,可能会这么作
    //写一个循环
    var total = 1
    for(var i=10; i>=1; i++){
        total *= i ;
    }
    这样的for循环简单直接。。。你们都会写
    可是,咱们能够写一个函数,递归调用
    //递归函数
    function jiecheng( n ){
        if ( 1===n) return 1
        return n*jiecheng(n-1)
    }
    //调用递归函数
    var total = jiecheng(10)

ps:两种不一样的方法,虽然结果都相同,可是仍是有区别的。递归并无经过for循环遍历每个数,并且代码量变少了,看起来有点高大上。javascript

  • 其实,在递归调用的时候,就是按照return的特定来执行的。由于return只有在遇到一个具体的值才会返回给调用者。
  • 而后,在调用的时候,会有一个'栈'的数据结构(先进后出,后进先出),存储每个调用的时状态,直到遇到一个可以有具体值的状态,就逐层往上返回给调用者,最终的值就是你想要的值。

递归的缺点html

  • 每次调用本身的时候,其实一直都是在占用着内存,占用资源较大。

闭包

  • 什么是闭包?
    咱们先来回顾一下,在es5里,用var定义的变量,不论是在代码块里定义,仍是在for循环里的局部变量,咱们都可以访问到这个变量,这就叫作全局变量。若是咱们在一个函数里用var定义变量,就是一个局部变量了,只有内部可使用。
//定义全局变量
    var a =1;

    //函数体定义变量
    function fun(){
        var b =1;
    }

    //代码块里定义变量
    {
        var c = 1
        {
            var d = 'rainbow'
        }
        
    }
    //for函数里的变量
    for( var i = 0 ; i<10 ;i++){
        console.log(i)
    }
        console.log( a , c , d , i )//1 1 "rainbow" 10
        console.log(b)//error

ps:上面代码能够看出来,在JavaScript里,除了方法体内的变量未局部变量,其余的都是全局变量,那若是咱们想要访问函数里面的变量该怎么办呢??
这个时候,咱们就要用到闭包了。java

  1. 在函数内自定义一个方法,返回函数定义的局部变量。
  2. 调用的时候,咱们先调用外层的函数,获得的是一个函数体,而后再一次调用,就可以获取到outer的内部成员的变量了。
function outer(){
        var num = 10;

        funtion inner(){
            console.log(num)
        }
        return inner;
    }

    var fun = outer()
    fun()//10

    或者

    function outer() {

        var age = 20;

        return function () {//匿名函数
            return age;
        }
    }
    var age1 = outer();
    console.log(age1())//20

总结:闭包,就是在函数内部定义一个函数,把function里私有的属性,经过这个内部函数返回给了外面。
特色:面试

  1. 经过闭包能够读取函数内部的变量
  2. 每一次调用最外层的方法,实际都是从新开辟一块内存空间., 由于返回的inner方法没有关闭,一直占用着内存,咱们能够手动关闭 outer = null
  3. 在outer里定义的变量,经过闭包获取到的成员变量,其实都是静态static变量,正如第2点所说,变量仍是存在内存中,并无主动释放。

闭包的缺点浏览器

  • 和递归相似,一直占用着内存资源,可能致使内存泄漏。

可能我本身讲的不够全,你们看看大佬的文章数据结构

完全理解闭包
http://www.javashuo.com/article/p-oqlutxhq-o.html
阮一峰老师的
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html闭包

回调函数

回调函数有个比较逼格的名字——句柄。咱们只要知道有这么个官方的叫法就行,之后面试或者交流的时候,也不至于听不懂这是啥东西。
简单理解就是,把一个函数看成参数。那么这个函数就是回调函数。
那为啥叫回调呢?
那是由于你执行一个方法时候,还不可以预期或者肯定会有什么样的结果,必须得再回过头来调用这个函数(也就是传的参数),获得具体的结果。异步

function fun(callback){
        console.log(callback)
    }
    //把一个方法看成参数

    function say (value) {
    alert(value);
    }
    alert(say);
    alert(say('hi js.'));

ps:回调函数应用场景多用在使用 js 写组件时,尤为是组件的事件不少都须要回调函数的支持。函数

内置函数

其实,咱们js的类库提供了不少的函数,好比常常用的console.log(),alert()等等。可是在还未学习面向对象以前,主要来了解两个内置函数,定时器setTimeout和setInterval学习

//使用方法
    setTimeout(callback,delay);
    setInterval(callback,delay);

    function callback(){
        console.log('rainbow');
    }

    var delay = 1*1000;

    //解释一下
    callback:定时器要执行的方法
    delay:定时器执行方法的间隔。单位ms毫秒

setTimeout、setInterval区别

  • setTimeout 只能执行一次,而setInterval一直执行。

那么如何中止定时器呢?
每一个定时器都会返回一个定时器id,这个id在线程池中存着,咱们接收他的id,而后清除

//接收id
    var id1 = setTimeout(callback,delay);
    var id2 = setInterval(callback,delay);

    //关闭定时器
    clearTimeout(id1)
    clearInterval(id2)

ps:

  1. 关闭定时器,clearTimeout或者clearInterval均可以关闭对方的id,由于他们共用一个定时器ID poor。
  2. delay这个参数,并不会很精确,由于这和时间片轮转有关。要想了解更多,能够去学习一下操做系统,进程和线程是什么。

其实,学习定时器的时候,咱们就应该了解一下,js里只有单线程,并且理论是没有异步操做的,你们口中说的那是模拟异步,那么你们就须要了解一个叫作任务队列的东西。
说到这里,咱们就来讲三个任务,其实还有不少的:

  • 渲染队列:好比浏览器的渲染,ie的hasLayout
  • 事件队列:好比点击事件onclick
  • 定时器队列:必定会等主程序执行完毕后再执行
    这些都是有必定执行顺序的,渲染队列->事件队列->定时器队列,因此定时器这个玩意,就像个弃儿,凡事都要最后才能拥有,这也就知道为啥你给他设置delay时间的时候,不会那么精确了。

谢谢你们能读完这篇随笔,鄙人学识浅薄,不少地方讲的自认为不是很深刻,也比较的俗,见谅见谅...

相关文章
相关标签/搜索