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时间的时候,不会那么精确了。

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

(0)

相关推荐

  • 详解JS中定时器setInterval和setTImeout的this指向问题

    前言 Js是一个单线程语言,可以通过setTimeout()和setInterval()来设置代码在指定时刻运行,前者是在指定时间后执行,后者是指每隔一段时间执行.两者的使用方法类似. 最近在练习写一 ...

  • 一文带你了解如何排查内存泄漏导致的页面卡顿现象

    "脚本之家 ",与百万开发者在一起 作者 | 零一0101 来源 | 前端印象(ID: Lpyexplore) 不知道在座的各位有没有被问到过这样一个问题:如果页面卡顿,你觉得可能 ...

  • 从一个超时程序的设计聊聊定时器的方方面面

    目录 如何设计一个靠谱的超时程序 JS引擎的运行机制是怎样的? 如何避免程序卡顿? 如何判断H5程序是从后台台恢复过来的? 如何理解定时器的丢弃行为? 在开发中如何选择使用合适的定时器? 有没有一键回 ...

  • JS数据结构与算法学习笔记大全 (温故而知新,可以为师矣。)

    目录: 6.1 概念 6.2 树的存储结构 6.3 二叉树 6.4 二叉搜索树 5.1概念 5.2 js实现一个简单哈希表: 5.3 处理冲突 4.3.1 原型链实现继承: 4.1 概念 4.2 js ...

  • 17K star 仓库,解决 90% 的大厂基础面试题

    前言 笔者开源的前端进阶之道已有三年之久,至今也有 17k star,承蒙各位读者垂爱.在当下部分内容已经略微过时,因此决定提笔翻新内容. 翻新后的内容会全部集合在「干爆前端」中,有兴趣的读者可以前往 ...

  • JavaScript入门-函数function(一)

    js函数(function) function的英文是[功能],[数] 函数:职责:盛大的集会的意思 在js里,就是函数的意思.在Java里叫做方法. 定义函数 function fun(参数){ / ...

  • JavaScript入门-对象(二)

    JavaScript对象(二) 本篇,主要讲了面向对象.this的指向问题,模拟继承过程 面向对象编程 什么面向对象编程? 编程,编程就是人们用计算机能懂的语言,告诉计算机自己想做的事情. 面向对象的 ...

  • 鉴赏丨新石器彩陶的入门知识(二)

    马家窑文化因1924年首次发现甘肃省临洮县马家窑村遗址而得名[1],其年代约在公元前3300年至2050年(碳十四测年为公元前3190-1715年),是仰韶文化晚期在甘肃.青海地区的一个分支,属于仰韶 ...

  • 中医基础入门,十二经络动图一目了然,值得存十年!

    古人将时间分为十二时辰,而我们十二经脉是左右对称地分布人体两侧,十二时辰与十二经络相对应,不同时辰对应不同的经络,我们可以根据这些来进行养生保健. 下面这些经络的走向动画图可以为大家提供参考. 手太阴 ...

  • 《易经》入门基础教程二

    上篇讲了易经最基础的八卦和先天八卦图.后天八卦图,今天的内容要比昨天深入一点,要讲的知识点有三个:64卦的形成与读法,六爻卦中"爻"的称呼,当位与不当位.我会用最通俗易懂的语言来表 ...

  • 雕塑作品欣赏入门(十二)

    雕塑作品欣赏入门(十二) 撰文|银牌艺术馆 顾问|吴志鹏 第三章 雕塑的分类之四 - 风格 <巴尔扎克>罗丹,法国 收藏于法国巴黎罗丹博物馆 在中外艺术发展史上,涌现了许多不同的风格流派, ...

  • 一些简单的错误处理函数(二)

    一些简单的错误处理函数(二) 接下来,我们继续学习 PHP 中的错误处理函数.上次学习过的函数是错误信息的获取.设置.发送等功能,今天学习的内容主要是关于错误的捕获相关的函数. set_error_h ...

  • [PHP小课堂]一些简单的错误处理函数(二)

    [PHP小课堂]一些简单的错误处理函数(二) 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学习资料 B ...

  • PHP中的文件系统函数(二)

    PHP中的文件系统函数(二) 这次我们来学习的是一些不是太常用,但却也非常有用的一些函数.它们中有些大家可能见过或者使用过,有一些可能就真的没什么印象了.它们都是 PHP 中文件系统相关操作函数的一部 ...