JavaScript的函数进阶
函数进阶
1立即执行函数表达式
立即执行的函数表达式的英文全称为Immediately Invoked Function Expression,简称就为IIFE。这是一个如它名字所示的那样,在定义后就会被立即调用的函数。
使用IIFE来进行初始 化,这样不会污染到全局环境。
通过IIFE,我们可以对我们的代码进行分块。并且块与块之间不会互相影响,哪怕有同名的变量 也没问题,因为IIFE也是函数,在函数内部声明的变量是一个局部变量
全局作用域是指声明的变量可在当前环境的任何地方使用。
函数作用域则只能在当前函数所创造的环境中使用。
块级作用域是指每个代码块也可以有 自己的作用域。
用var声明的变量是不存在块级作用域的,所以即使在if块中用var声明变量,它也能在外 部的函数或者全局作用域中使用
解决这个问题有两种方法,第一:使用ES6中的let关键字声明变量,这样它就有块级作用域。 第二:使用IIFE
2变量初始化
1执行上下文
在ECMAScript中代码的运行环境分为以下三种:
・全局级别的代码:这是默认的代码运行环境,一旦代码被载入,JS引擎最先进入的就是这个环境
・函数级别的代码:当执行一个函数时,运行函数体中的代码。
・EvaI级别的代码:在EvaI函数内运行的代码。
・不管什么情况下,只存在一个全局的上下文,该上下文能被任何其它的上下文所访问到。也 就是说,我们可以在test的上下文中访问到全局上下文中的o ne变量,当然在函数test2或者 test3中同样可以访问到该变量。
・至于函数上下文的个数是没有任何限制的,每到调用执行一个函数时,引擎就会自动新建出 —个函数上下文,换句话说,就是新建一个局部作用域,可以在该局部作用域中声明私有变 量等,在外部的上下文中是无法直接访问到该局部作用域内的元素的。
对于执行上下文这个抽象的概念,可以归纳为以下几点:
・单线程
· 同步执行
・唯一的一个全局上下文
・函数的执行上下文的个数没有限制
・每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此。
2函数上下文的建立与激活
每当我们调用一个函数时,一个新的执行上下文就会被创建出来。然而,在 js引擎的内部,这个上下文的创建过程具体分为两个阶段,分别是建立阶段和代码执行阶段。
建立阶段:发生在当调用一个函数,但是在执行函数体内的具体代码之前
•建立变量对象(arguments对象,形式参数,函数和局部变量)
•初始化作用域链
•确定上下文中this的指向对象
代码执行阶段:发生在具体开始执行函数体内的代码的时候
•执行函数体内的每一句代码
我们将建立阶段称之为函数上下文的建立,将代码执行阶段称之为函数上下文的激活。
变量对象
将整个上下 文看做是一个对象以后得到的一个词语。具体来讲,我们可以将整个函数上下文看做是一个对 象,那么既然是对象,对象就应该有相应的属性。对于我们的执行上下文来说,有如下的三个属 性:
变量对象,作用域链以及this
在函数的建立阶段,首先会建立arguments对象。然后确定形式参数,检查当然上下文中的函数 声明,每找到一个函数声明,就在variableObject下面用函数名建立一个属性,属性值就指向该 函数在内存中的地址的一个引用。如果上述函数名已经存在于variableObject(简称V0)下面,那 么对应的属性值会被新的引用给覆盖。最后,是确定当前上下文中的局部变量,如果遇到和函数 名同名的变量,则会忽略该变量。
在建立阶段,除了arguments,函数的声明,以及形式参数被赋予了具体的属性值 外,其它的变量属性默认的都是undefinedo并且普通形式声明的函数的提升是在变量的上面的。
3作用域链
所谓作用域链,就是内部上下文所有变量对象(包括父变量对象)的列表。此链主要是用于变量查 询。
公式作用域链(ScopeChain) = AO + [[scope]]
A0,简单来说就是VO, AO全称为active object(活动对象),对于当前的上下文来讲,一般 将其称之为A0,对于不是当前的上下文,一般被称为V0
[[scope]]:所有父级变量对象的层级列表(也被称之为层级链)
[[scope]],有一个一个非常重要的特性,那就是[[scope]]是在函数创建的时候,就已经被存 储了,是静态的。所谓静态,就是说永远不会变,函数可以永远不被调用,但是[[scope]]在创建 的时候就已经被写入了,并且存储在函数作用域链对象里面。
3闭包
1闭包基本介绍
在一个函数的外部,可以访问并使用它内部的变量
狭义的闭包
・形成闭包环境的函数能够被外部变量引用,这样就算它外部上下文销毁,它依然存在。
・在内部函数中要访问外部函数的局部变量。
优 点
・通过闭包可以让外部环境访问到函数内部的局部变量。
・通过闭包可以让局部变量持续保存下来,不随着它的上下文环境一起销毁。
2闭包的更多作用
1.封装变量
闭包可以帮助把一些不需要暴露在全局的变量封装成"私有变量"。
2.延续局部变量的寿命
3闭包和面向对象设计
过程与数据的结合是形容面向对象中的"对象"时经常使用的表达。对象以属性的形式包含了数 据,以方法的形式包含了过程。而闭包则是在过程中以环境的形式包含了数据。通常用面向对象 思想能实现的功能,用闭包也能够实现,反之亦然。
4递归函数
递归函数是一个一直直接或者间接调用它自己本身,直到满足某个条件才会退出的函数。
let numCalc = function(i){
if(i == 1)
{
return 1;
}
else{
return i * numCalc(i-1);
}
}
console.log(numCalc(4));//24
1•使用递归计算从m加到n
let numCalc = function (m, n) {
if (m === n) {
return m;
}
else {
return n + numCalc(m, m > n ? n + 1 : n - 1);
}
}
console.log(numCalc(100, 1));//5050
2•使用递归计算出某一位的斐波那契数
let numCalc = function (i) {
if (i == 1) {
return 0;
}
else if (i == 2) {
return 1;
else {
return numCalc(i - 1) + numCalc(i - 2); }
} console.log(numCalc(8));//13
3•使用递归打印出多维数组里面的每一个数字
let arr = [1, 2, [3, 4, [5, 6], 7, 8], 9, 10]; let test = function (arr) {
for (let i = 0; i < arr.length; i++) { if (typeof arr[i] == 'object') { test(arr[i]);
}
else { console.log(arr[i]);
}
}
};
test(arr);
5高阶函数
1高阶函数介绍
高阶函数(higher-order-function)指的是操作函数的函数,一般有以下两种情况:
・函数可以作为参数被传递
・函数可以作为返回值输出
2参数传递
1.回调函数
在Ajax异步请求的应用中,回调函数的使用非常频繁。想在Ajax请求返回之后做一些事情,但又 并不知道请求返回的确切时间时,最常见的方案就是把回调函数当作参数传入发起Ajax请求的方 法中,待请求完成之后执行回调函数。
一个函数不适合执行一些请求时,也可以把这些请求封 装成一个函数,并把它作为参数传递给另外一个函数,"委托"给另外一个函数来执行。
2.数组排序
sort()方法 封装了数组元素的排序方法。把可变的部分封装在函数参数里, 动态传入sor t()方法,使sor t()方法方法成为了一个非常灵活的方法。
for Each() , map() , eve ry() , some()等函数,也 是常见的回调函数。
3返回值输出
1.判断数据的类型
使用 Object,prototype.toString 来计算
Object.prototype.toString.call(obj)返回一个字符串
2. getSingle
4面向切面编程
AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务 逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后,再通 过"动态织入"的方式掺入业务逻辑模块中。这样做的好处首先是可以保持业务逻辑模块的纯净和 高内聚性,其次是可以很方便地复用日志统计等功能模块
在JavaScript中实现AOP, 都是指把一个函数"动态织入"到另外一个函数之中。
6高阶函数的其他应用
函数节流(throttle)或函数去抖(debounce),核心其实就是限制某一 个方法的频繁触发
1函数防抖
函数防抖的原理是将即将被执行的函数用setTimeout延迟一段时间执行。对于正在执行的函数和 新触发的函数冲突问题有两种处理,也分别对应了定时器管理的两种机制。
第一种是只要当前函数没有执行完成,任何新触发的函数都会被忽略
第二种是只要有新触发的函数,就立即停止执行当前函数,转而执行新函数
下面是一 个比较完整的防抖函数(debounce),该函数接受2个参数,第一个参数为需要被延迟执行的函 数,第二个参数为延迟执行的时间
2函数节流
数节流使得连续的函数执行,变为固定时间段间断地执行。关于节流的实现,有两种主流的实 现方式,一种是使用时间戳,一种是设置定时器。
1.使用时间戳
触发事件时,取出当前的时间戳,然后减去之前的时间戳(最一开始值设为0),如果大于设置的 时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。
2.使用定时器
触发事件时,设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执 行,然后执行函数,清空定时器,这样就可以设置下个定时器。
JavaScript的函数进阶的更多相关文章
- 深入理解javascript函数进阶系列第一篇——高阶函数
前面的话 前面的函数系列中介绍了函数的基础用法.从本文开始,将介绍javascript函数进阶系列,本文将详细介绍高阶函数 定义 高阶函数(higher-order function)指操作函数的函数 ...
- 带你学习Javascript中的函数进阶(一)
1. 函数的定义和调用 1.1 函数的定义方式 函数声明方式function关键字(命名函数) 函数表达式(匿名函数) new Function() var fn = new Function('参数 ...
- 【转】Python之函数进阶
[转]Python之函数进阶 本节内容 上一篇中介绍了Python中函数的定义.函数的调用.函数的参数以及变量的作用域等内容,现在来说下函数的一些高级特性: 递归函数 嵌套函数与闭包 匿名函数 高阶函 ...
- JavaScript中函数函数的定义与变量的声明<基础知识一>
1.JavaScript中函数的三种构造方式 a.function createFun(){ } b.var createFun=function (){ } c.var createFun=new ...
- 理解 JavaScript 回调函数并使用
JavaScript中,函数是一等(first-class)对象:也就是说,函数是 Object 类型并且可以像其他一等对象(String,Array,Number等)一样使用.它们可以"保 ...
- 5种 JavaScript 调用函数的方法
一次又一次的,我发现,那些有bug的Javascript代码是由于没有真正理解Javascript函数是如何工作而导致的(顺便说一下,许多那样的代码是我写的).JavaScript拥有函数式编程的特性 ...
- 潭州学院-JavaVIP的Javascript的高级进阶-KeKe老师
潭州学院-JavaVIP的Javascript的高级进阶-KeKe老师 讲的不错,可以学习 下面是教程的目录截图: 下载地址:http://www.fu83.cn/thread-283-1-1.htm ...
- javascript escape()函数和unescape()函数
javascript escape()函数和unescape()函数 escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串. 语法: escape(string) stri ...
- JavaScript调用函数的方法
摘要:这篇文章详细的介绍了Javascript中各种函数调用的方法及其原理,对于理解JavaScript的函数有很大的帮助! 一次又一次的,我发现,那些有bug的Javascript代码是由于没有真正 ...
随机推荐
- 结对编程UI
GitHub:https://github.com/zsl1996/UI/commits/master 一. 实验内容 这是交付给最终用户的软件,有一定的界面和必要的辅助功能.完 ...
- Spring Boot 自定义注解,AOP 切面统一打印出入参请求日志
其实,小哈在之前就出过一篇关于如何使用 AOP 切面统一打印请求日志的文章,那为什么还要再出一篇呢?没东西写了? 哈哈,当然不是!原因是当时的实现方案还是存在缺陷的,原因如下: 不够灵活,由于是以所有 ...
- ZMQ面面观
ZMQ是什么? 这是个类似于Socket的一系列接口,他跟Socket的区别是:普通的socket是端到端的(1:1的关系),而ZMQ却是可以N:M 的关系,人们对BSD套接字的了解较多的是点对点的连 ...
- SQL Server 获取所有库名
----1. 获取所有的数据库名----- SELECT NAME FROM MASTER.DBO.SYSDATABASES ORDER BY NAME -----2. 获取所有的表名------ ...
- delphi xe10 网络文件传送
//网络传送文件(类似Server/Client) TTetheringManager|设备管理.TTetheringAppProfile|文件发送 待补充
- Delphi 数学函数:常用的几个数学函数(Power、Abs、Int、Trunc、Round、Frac、sqr、sqrt)
Delphi 常用的几个数学函数 1 Power函数,求次方 定义:function Power(X,Y): (Same type as parameter); 说明:X可以是整型,也可以是实型:返回 ...
- 【NOI2019模拟2019.7.1】三格骨牌(轮廓线dp转杨图上钩子定理)
Description \(n,m<=1e4,mod ~1e9+7\) 题解: 显然右边那个图形只有旋转90°和270°后才能放置. 先考虑一个暴力的轮廓线dp: 假设已经放了编号前i的骨牌,那 ...
- Quick BI功能篇之(一):20分钟入门
前言: 最近小编帮助隔壁团队一个小姐姐解决了个大难题:给老板汇报业绩分析,频次提高.效率提升,还得保证团队中的小伙伴们都得有点大数据时代的基本数据能力.小编觉得这么好的经验可以分享给更多志同道合的朋友 ...
- composer(作曲家)安装php-ml
刚开始我用的是up5.6版本php命令安装composer 后来使用composer时发现命令行会提示php版本太低 于是我下载了wamp,使用7.1版本的php重新安装了composer,因为php ...
- Java高新技术第三篇:注解的使用
我们知道注解是在JDK1.5引入的,可能有的人没有用过注解,所以感觉注解这个东西没有什么用,但是深入了解注解,对以后学习框架有所帮助的,后面提到的JavaWeb的框架中很多都是基于注解的技术, 其实注 ...