优秀的编程知识分享平台

网站首页 > 技术文章 正文

JSCORE function、作用域和闭包(js中函数的作用域分为)

nanyue 2024-07-25 06:09:18 技术文章 12 ℃

正课:

1. ***Function

重载

匿名函数

2. *****作用域和作用域链

3. *****闭包

1. ***Function:

什么是: js中一切函数都是对象

函数对象是专门封装函数定义的对象。

创建: 3种:(若为同名函数,后面的会替换前面的)

1. 声明: function 函数名(参数列表){函数体; return 返回值;}

何时: 只要一段代码被反复使用,都要先定义在一个专门的函数中,再反复调用函数即可——复用

何时使用参数: 只要函数步骤中必须某些数据才能正常执行时,就要定义参数。

何时使用返回值: 如果函数的调用者需要函数的执行结果时,函数就必须返回值。

可被声明提前:

****声明提前(hoist): 在开始执行程序前,将所有var声明的变量和function声明的函数提前到*当前作用域*的顶部,集中创建。

*******************赋值留在原地!*****************

2. 函数直接量:

var 函数名=function(参数列表){函数体; return 返回值;};

不会被声明提前。

何时: 只要不希望被声明提前时。

揭示了: 函数名仅是一个普通的变量

函数定义其实是一个对象

函数名中仅保存了函数对象的地址——引用

3. (比较罕见,所有形参必须放在引号中)用new:

var fun=

new Function("参数1","参数2",...,"函数体; return 返回值")

笔试: function compare(a,b){return a-b;}

var compare=function(a,b){return a-b;}

var compare=new Function("a","b","return a-b;");

***重载(overload):

什么是: 相同函数名,不同参数列表的多个函数,在调用时,可根据传入参数的不同,自动选择对应的函数调用!

为什么: 减轻调用者的负担,一个函数名,可执行多种操作

何时: 一项任务,根据不同的参数,执行不同的操作流程时

如何: js语法不支持重载效果!!!!(因为js不允许多个同名函数同时存在,Java标识函数是函数名加列表)

变通: 所有函数对象内,都自动内建了一个arguments对象

arguments对象:

专门保存传入函数的所有参数值的类数组对象

类数组对象: (object like array)即长得像数组的对象

vs 数组: 相同: 下标, length, for遍历

不同: 类数组对象是Object,不是Array,无法使用Array的API

数组是Array类型,可以使用数组类型所有的API

重载必须得用,运用了的有splice(),toString()......

匿名函数:

什么是: 函数创建时,不被任何变量引用的函数

为什么: 节约内存

何时: 如果一个函数只用一次,用完希望自动释放时

如何:2种

1. 回调callback: 将函数作为参数传递给另一个函数去调用

比如: arr.sort(function (a,b){return a-b});

str.replace(/reg/g,function(kw,$1,...){return ...})

2. 自调: 创建函数后立刻调用自己!

何时: 如果一段代码,不希望其中的变量造成全局 的污染,全局变量容易受到篡改,就将其放在匿名函数中

为什么: 建立临时作用域!避免全局污染!

如何:

+function(参数列表){

函数体; return 返回值}();

2. *****作用域和作用域链

作用域scope:

什么是: 一个变量的使用范围——使用

本质上作用域是一个对象——存储

作用域中的变量都是对象的成员

包括:2种

1.全局作用域:(全局变量)随处可用,可反复使用——全局污染

2.函数作用域:(局部变量)仅函数内使用,不可重复使用。

函数的生命周期:

第一阶段:开始执行前:创建执行环境栈(数组):临时保存正在执行的函数的执行环境,向执行环境栈中压入第一个默认函数main();创建全局对象window

第二阶段:定义函数时:创建函数对象,封装函数定义;声明函数名变量,引用函数对象;函数对象的scope属性引用回,创建函数时的作用域;

第三阶段:调用函数时:ECS中压入一个新的元素(执行环境)记录新函数的调用;创建一个活动对象:函数作用域对象,保存本次函数调用用到的局部变量;ECS中的新执行环境元素,引用活动对象,活动中的parent属性引用函数的scope指向的父级作用域对象(即从活动对象指向window:全局作用域对象)。执行过程中优先使用活动对象中的局部对象,若无,就找parent,全局也无,则报错。

第四阶段:函数调用后:执行环境栈中本次函数的执行环境出栈,导致活动对象被释放,

程序/函数的执行过程:

1. 开始执行程序前:

创建ECS(执行环境栈):

依次保存每个调用的函数的执行环境

在ECS中压入第一个全局执行环境(全局EC)

创建window对象,全局EC引用window对象

window就是全局作用域对象

2. 开始执行程序:

所有全局变量都保存在全局作用域对象window中

3. 定义函数时:

在全局添加函数名变量

创建函数对象封装函数定义

函数名变量引用函数对象

函数对象中有一个scope属性,引用回创建函数时的作用域对象。通常都是window。

4. 调用函数时:

在ECS中压入一个新的EC

为本次函数调用创建专门的活动对象(AO)

在AO中创建所有函数定义中规定的局部变量

其实AO就是函数作用域对象

所有局部变量都是AO的成员

新的EC引用活动对象AO

AO的parent指向window

变量的使用顺序:

先用AO(函数作用域)中的局部变量

如果AO中没有,才去window(全局作用域)中找

5. 函数调用后:

本次函数调用的EC出栈

导致函数作用域对象AO释放

导致局部变量一同释放

作用域链(scope chain): 由多个作用域对象连续引用形成的链式结构。掌管着一切变量的使用顺序

顺序: 先函数作用域对象AO->延作用链向父级作用域找

所有的变量都保存在作用域链上的对象中

局部变量都保存在函数作用域对象AO中

全局变量都保存在全局作用域对象window中

控制了: 变量的使用顺序

先用AO(函数作用域)中的局部变量

如果AO中没有,才去window(全局作用域)中找

3.闭包:

什么是: 即重用变量,又防止变量被污染的一种机制

为什么: 全局变量: 优: 可重用 缺: 易被全局污染

局部变量: 优: 不会被污染 缺: 不可重用

何时: 既重用变量,又防止变量被污染

如何: 3步:

1. 用外层函数包裹住受保护的变量和操作变量的内层函数

2. 外层函数将内层函数返回到外部,被外部的变量保存

3. 通过外部变量调用内层函数,访问受保护的变量

缺: 1. 占用更多内存: 外层函数的AO

2. 容易造成内存泄漏

三特点: 1. 函数嵌套:

2. 外层函数包含一个受保护的局部变量

3. 外层函数将内层函数对象返回

有几个闭包就看有几个受保护的变量

闭包如何形成:外层函数的作用域对象(AO)无法释放,即此中outer的AO无法释放

笔试:

1、先找受保护的变量,判断外层函数执行后变量的结果

2、再找操作变量的内层函数:

1、被外层函数return到外部的

2、也可通过直接给全局变量赋值一个函数的方式

Tags:

最近发表
标签列表