美文网首页
探索JS的函数表达式(你不知道的js)

探索JS的函数表达式(你不知道的js)

作者: 阿飞去捉小蝴蝶 | 来源:发表于2019-05-05 17:55 被阅读0次

函数是js中既强大又容易令人困惑的特性,首先定义函数的方法有两种:函数声明和函数表达式

定义函数的两种方法

许多浏览器给函数定义了一个非标准的name属性,console.log(functionName.name) =》 “functionName”,匿名函数的name属性则是一个空的字符串

函数声明的重要特征就是函数声明提升,可以在声明函数之前调用

在函数内部使用函数声明定义函数,只能创建局部函数


递归

递归函数是一个函数通过名字调用自身的情况下构成的

递归

arguments.callee是一个指向正在执行的函数的指针,在这里等同于factorial(num-1)


闭包

闭包就是指有权访问另一个函数内部变量的函数,通常是一个函数包含一个函数的形式,这句话大多数前端er都知道,但如何去理解闭包呢

首先要理解作用域和作用域链的问题,当某个函数被调用时,会创建一个执行环境以及相应的作用域链,然后,使用arguments和其他命名参数来初始化函数的活动对象,在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,以此类推,直至全局对象,也就是作用域链的终点:全局执行环境,举个🌰

创建闭包函数

后台的每个执行环境都有一个表示变量的对象——变量对象,全局环境的变量始终存在(window),而像createComparisonFunction()函数这样的局部环境的变量对象,只在函数执行时存在,在创建createComparisonFunction()函数时,会预先创建一个包含全局变量对象的作用域链,被保存在内部的[[Scope]]属性中,这个对象对应的是一个对象的列表,列表中的对象仅能javascript内部访问,没法通过语法访问。

当调用createComparisonFunction()函数时,会为函数创建一个执行环境,然后通过复制函数的[[Scope]]属性中的对象,构建起执行环境的作用域链。作用域链的本质是一个指向变量对象的指针列表,只引用但不实际包含的变量对象。

调用compareNames()函数的过程中产生的作用域链之间的关系

通常函数执行完成,就是销毁局部活动对象,但上面的🌰中的匿名函数的作用域链包含了外部函数的活动对象,所以即使外部函数执行完毕,其局部活动对象也不会销毁,直到匿名函数被销毁。

闭包与变量

由于作用域链的配置机制是一个引用,所以闭包只能获取包含函数中任何变量的最终值。🌰

闭包函数的引用值

由于这里没有参数传递,这里的i是作用域链中引用的对象,即使它的值是基本类型,所以这里输出10个10。

想要获得0-9这样的结果,可以将i作为实参传递给匿名函数的形参,中间是有一个复制的操作,或者使用ES6的let,详情参考这里

this对象

this对象是在运行时基于函数的执行环境进行绑定的,全局环境中指向window,当函数被作为某个对象调用时,指向调用的对象。this始终指向直接调用它的对象。

每个函数在被调用时,会自动取得两个特殊的变量this和arguments,内部函数搜索这两个变量时,只会在活动对象里搜索,并不会向上查找。可以通过变量赋值的方法实现访问。

内存泄漏

众所周知,js在函数执行完毕后会通过垃圾回收机制将函数内部的活动对象销毁,而闭包函数由于作用域链一直引用对象,所以不能销毁,这样就很容易造成内存泄漏问题,所以使用的时候也要记得手动销毁。


模仿块级作用域

js是没有块级作用域的概念的,所以在块语句中定义的变量,实际是包含在函数中的变量,而非语句中的变量。

私有变量

任何函数中定义的变量,都可以认为是私有变量,因为不能从外部访问到。

有权访问私有变量和私有函数的公有方法叫特权方法

利用私有和特权成员,可以隐藏那些不想被直接修改的数据。🌰

在构造函数中定义特权方法

静态私有变量

通过在私有作用域中定义私有变量和函数,创建特权方法。🌰

创建特权方法

这个🌰中的Person构造函数和setName()和getName()方法一样,都有权访问私有变量name,这种模式下,变量name就变成一个静态的,由所有实例共享的属性。

模块模式

模块模式是为单例(只有一个实例)创建私有变量和特权方法。🌰

模块模式创建特权方法

这里的单例就是application,私有对象components数组,返回对象的getComponentCount()和registerComponent()方法都是有权访问components对象的特权方法。

增强的模块模式

在返回对象之前加入对其增强的代码,这种模式适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其增强情况。🌰

增强的模块模式

小结

本文仅是个人的看法,如有错误和补充,欢迎指正和交流。

参考红皮书的一些学习所得

相关文章

  • js ------ 函数声明和函数表达式

    js创建对象几种方式 js 函数声明 和 函数表达式函数声明 函数表达式 函数表达式: 下面的函数都会直接运行

  • 探索JS的函数表达式(你不知道的js)

    函数是js中既强大又容易令人困惑的特性,首先定义函数的方法有两种:函数声明和函数表达式 许多浏览器给函数定义了一个...

  • 函数表达式

    以下内容总结自《JS高级程序设计》第三版 什么是函数表达式? 函数表达式,是JS中定义函数的一种方式。在JS中,共...

  • JS函数与作用域

    函数声明和函数表达式有什么区别 使用函数声明时,在执行js语句的时候,会先把函数提升到js语句的顶部,所以即使函数...

  • JavaScript 05 函数

    js函数的概念和作用,js函数的定义,js函数的调用,js事件驱动的概念,js函数的实参和形参,js的作用域,js...

  • js变量声明提升与函数表达式

    1.变量声明提升 js引擎会把变量声明与函数声明都提升到当前函数的顶部。eg: js引擎编译为 2.函数表达式 对...

  • JavaScript基础学习笔记(二)

    函数定义 函数的声明 函数表达式 JS函数可以通过一个表达式定义,函数表达式可以存储在变量中。当存储在变量中之后,...

  • eval介绍

    eval 的定义和用法 如果参数是表达式,eval()函数会执行表达式;如果参数是 js 语句,eval()函数会...

  • 函数

    一、问答 函数声明和函数表达式有什么区别? Js中的函数声明是指下面的形式: 函数表达式则是类似表达式那样来声明一...

  • javascript 函数声明 && 函数表达式

    函数声明:在js解释时进行函数提升,在同一个作用域内,不管函数在哪声明,都可以调用。函数表达式:在js运行时进行时...

网友评论

      本文标题:探索JS的函数表达式(你不知道的js)

      本文链接:https://www.haomeiwen.com/subject/jlnmdftx.html