位置: 编程技术 - 正文

详解Javascript函数声明与递归调用(javascript函数的定义)

编辑:rootadmin

推荐整理分享详解Javascript函数声明与递归调用(javascript函数的定义),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:javascript function(),javascript函数怎么写,javascript函数用法,javascript中的函数该如何理解,js函数详解,javascript函数用法,js函数详解,javascript中的函数该如何理解,内容如对您有帮助,希望把文章链接给更多的朋友!

Javascript的函数的声明方式和调用方式已经是令人厌倦的老生常谈了,但有些东西就是这样的,你来说一遍然后我再说一遍。每次看到书上或博客里写的Javascript函数有四种调用方式,我就会想起孔乙己:茴字有四种写法,你造吗?

尽管缺陷有一堆,但Javascript还是令人着迷的。Javascript众多优美的特性的核心,是作为顶级对象(first-class objects)的函数。函数就像其他普通对象一样被创建、被分配给变量、作为参数被传递、作为返回值以及持有属性和方法。函数作为顶级对象,赋予了Javascript强大的函数式编程能力,也带来了不太容易控制的灵活性。

1、函数声明

变量式声明先创建一个匿名函数,然后把它赋值给一个指定的变量:

通常我们不必关心等号右边表达式的作用域是全局还是某个闭包内,因为它只能通过等号左边的变量f来引用,应该关注的是变量f的作用域。如果f指向函数的引用被破坏(f = null),且函数没有被赋值给任何其它变量或对象属性,匿名函数会因为失去所有引用而被垃圾回收机制销毁。

也可以使用函数表达式创建函数:

与变量式不同的是,这种声明方式会为函数的一个内置属性name赋值。同时把函数赋值给当前作用域的一个同名变量。(函数的name属性,configurable、enumerable和writable均为false)

Javascript变量有一个的特别之处,就是会把变量的声明提前,表达式式的函数声明,也会把整个函数的定义前置,因此你可以在函数定义之前使用它:

函数表达式的声明会被提升到作用域顶层,试试下面的代码,它们不是本文的重点:

Crockford建议永远使用第一种方式声明函数,他认为第二种方式放宽了函数必须先声明后使用的要求从而会导致混乱。(Crockford是一个类似于罗素口中用来比喻维特根斯坦的"有良心的艺术家"那样的"有良心的程序员",这句话很拗口吧)

函数式声明

看起来是

的简写。而

的表达式,创建一个函数并把内置的name属性赋值为"b",然后把这个函数赋值给变量a,你可以在外部使用a()来调用它,但却不能使用b(),因为函数已被赋值给a,所以不会再自动创建一个变量b,除非你使用var b = a声明一个变量b。当然这个函数的name是"b"而不是"a"。

使用Function构造函数也可用来创建函数:

这种方式其实是在全局作用域内生成一个匿名函数,并把它赋值给变量f。

2、递归调用

详解Javascript函数声明与递归调用(javascript函数的定义)

递归被用来简化许多问题,这需要在一个函数体中调用它自己:

Javascript中函数的巨大灵活性,导致在递归时使用函数名遇到困难,对于上面的变量式声明,f是一个变量,所以它的值很容易被替换:

函数是个值,它被赋给fn,我们期待使用fn(5)可以计算出一个数值,但是由于函数内部依然引用的是变量f,于是它不能正常工作了。

函数式的声明看起来好些,但很可惜:

看起来,一旦我们定义了一个递归函数,便须注意不要轻易改变变量的名字。

上面谈论的都是函数式调用,函数还有其它调用方式,比如当作对象方法调用。

我们常常这样声明对象:

声明一个匿名函数并把它赋值给对象的属性(fac)。

如果我们想要在这里写一个递归,就要引用属性本身:

当然,它也会遭遇和函数调用方式一样的问题:

方法被赋值给obj2的fac属性后,内部依然要引用obj1.fac,于是…失败了。

换一种方式会有所改进:

通过this关键字获取函数执行时的context中的属性,这样执行obj2.fac时,函数内部便会引用obj2的fac属性。

可是函数还可以被任意修改context来调用,那就是万能的call和apply:

于是递归函数又不能正常工作了。

我们应该试着解决这种问题,还记得前面提到的一种函数声明的方式吗?

这种声明方式叫做内联函数(inline function),虽然在函数外没有声明变量b,但是在函数内部,是可以使用b()来调用自己的,于是

就这样,我们有了一个可以在内部使用的名字,而不用担心递归函数被赋值给谁以及以何种方式被调用。

Javascript函数内部的arguments对象,有一个callee属性,指向的是函数本身。因此也可以使用arguments.callee在内部调用函数:

但arguments.callee是一个已经准备被弃用的属性,很可能会在未来的ECMAscript版本中消失,在ECMAscript 5中"use strict"时,不能使用arguments.callee。

最后一个建议是:如果要声明一个递归函数,请慎用new Function这种方式,Function构造函数创建的函数在每次被调用时,都会重新编译出一个函数,递归调用会引发性能问题——你会发现你的内存很快就被耗光了。

标签: javascript函数的定义

本文链接地址:https://www.jiuchutong.com/biancheng/376008.html 转载请保留说明!

上一篇:微信和qq时间格式模板实例详解(微信和qq时间格式不一样)

下一篇:Javascript 实现简单计算器实例代码(javascript简明教程)

  • 个人所得税跨区域可以申报吗
  • 营业外收支计入哪里
  • 企业所得税税率
  • 分期付款方式购入货物会计分录
  • 附加税减半征收政策从什么时候开始
  • 盈亏平衡点产量越高,项目风险越大
  • 房屋预售交款怎么交
  • 收到客户定金账务怎么做
  • 收到投资款现金流量项目是什么
  • 税前扣除的职工教育经费
  • 上年的费用支出包括哪些
  • 个人借款无法收回确认坏账账务处理
  • 离退休人员再任职的规定
  • 解聘职工赔偿工资包括哪些
  • 研发废料收入实务中如何冲减研发费用?
  • 股东借款可以转为认缴出资
  • 认证专票税务处理怎么做?
  • 利息支出企业所得税税前扣除标准
  • 小企业存货有哪些
  • 社保刚办理可以用吗
  • 股东投入的资金可以计入资本公积吗
  • windows 10 bug
  • 无偿赠送的原材料怎么处理
  • 怎么免费获取百度文库的付费文档
  • 对账工作的主要内容为什么不包括账表核对
  • 高新技术企业的税收优惠政策
  • 赠与合同要公证吗有效吗
  • 公司提取员工公积金
  • 长期股权投资转出账务处理
  • 分公司收到总公司拨款怎么做分录
  • 租赁固定资产成本怎么算
  • 长期待摊费用如何结转
  • 增值税按简易计价方式
  • 计提职工养老保险金
  • 企业预付工程车租赁费
  • 合伙人资本属于股东吗
  • 递延所得税负债借贷方向
  • 应纳税所得额100-300万税率
  • 在建工程明细科目有土地使用权摊销吗
  • 建筑企业增值税收入确认时间
  • 注销公司怎么搞
  • DedeCMS V5.7 SP2前台文件上传漏洞
  • vue连接webapi
  • 交易性金融资产入账价值怎么计算
  • 影响公司股利分成的因素
  • 政府补助确认递延所得税负债
  • 应交税金科目的核算
  • 政府补助的界定
  • 合同权利义务包含债务吗
  • 资源税会计科目
  • 关税进口增值税缴纳时间
  • 私募基金公司收入高吗
  • 低值易耗品摊销借贷方向
  • 09年前的固定资产
  • 以前年度不合规发票如何调年报
  • 本期盈余为负数怎么调整
  • 专用发票怎么网上申领
  • 如何给初建单位发邮件
  • 深入浅出了解啥意思
  • 电脑windows怎么查
  • 电脑开机怎么设置默认系统
  • vista升级选项灰色
  • 服务器centos版本选择
  • 电脑无法使用qq
  • linux统计代码行数过滤空行
  • 英文xp系统中文语言包
  • win7安装kb4534310补丁失败
  • win8资源管理器未响应
  • 十大经典排序算法总结
  • nodejsapi框架
  • gitlab管理员账号 审批
  • 怎么在dos下运行
  • python supper函数
  • unity3d初学者教程视频
  • python爬虫全套教程
  • python数据结构教程
  • 使用jquery实现的项目
  • 广西电子发票如何申请
  • 科研用地是否缴纳土地使用税
  • 个人所得税优惠政策最新2023年度
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设