zoukankan      html  css  js  c++  java
  • 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循环遍历每一个数,而且代码量变少了,看起来有点高大上。

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

    递归的缺点

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

    闭包

    • 什么是闭包?
      我们先来回顾一下,在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里,除了方法体内的变量未局部变量,其他的都是全局变量,那如果我们想要访问函数里面的变量该怎么办呢??
    这个时候,我们就要用到闭包了。

    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点所说,变量还是存在内存中,并没有主动释放。

    闭包的缺点

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

    可能我自己讲的不够全,大家看看大佬的文章

    彻底理解闭包
    https://www.cnblogs.com/itjeff/p/10106855.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时间的时候,不会那么精确了。

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

  • 相关阅读:
    支付宝H5 与网页端支付开发
    java图片操作--生成与原图对称的图片
    java 图片的自定义大小
    微信公众号开发(2)---消息的接收发送
    js 创建对象
    jqery多选
    金额大写转换
    js数字转换
    js日期格式转换
    java设计模式
  • 原文地址:https://www.cnblogs.com/lovelyk/p/14290830.html
Copyright © 2011-2022 走看看