博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面包屑之javascript声明期与执行期的故事
阅读量:4948 次
发布时间:2019-06-11

本文共 2512 字,大约阅读时间需要 8 分钟。

js中万物皆对象,特殊的对象(function类型)在声明和执行的时候会发生一些奇妙的事情,如下:

function a(){    var id = 1;        function b(){        alert(++id);                  }  return b;}var c = a();

上述代码,首先在全局作用域中声明了一个a,

函数a从定义到执行的过程为例阐述这几个概念。

  1. 定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”;   这里a是一个全局函数,  则a的作用域只有global对象.
  2. 当要执行函数a的时候,a会进入相应的执行环境(excution context)
  3. 在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即 a.scope = a.scope_chain = [global对象]
  4. 然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和global对象。
  5. 下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
  6. 把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。(所以的b执行时的作用域为   b的活动对象-->a的活动对象-->global对象)
  7. 最后逐步执行代码, 然后返回, 退出函数.

 

用伪代码描述

define function a:    a.scope_chain = [global]execute a:    a.scope = a.scope_chain      // [global]    call_object = {}    call_object.arguments = []        for key in localVariables:    // localVariables include formal parameter        call_object[key] = localVariables[key]        if key is function:            define function key: // the parents run time is always the childs define time           key.scope_chain = [a.call_object, global]    push call_object into a.scope // a.scope = [call_back, global]    execute a.inter_code

 

  

 

再回到代码  var c = a();  这时候把a()的返回值b函数指向c,然后c很神奇的可以访问到a的内部私有属性i了,这就是神奇的闭包了。

由于函数具有被调用时创建封闭环境的特性,因此在某些情况这种特性又被称为“闭包”

闭包自我理解:

   闭包应该是个抽象的概念,大概就是指function在执行时会创建的一个封闭环境,而这个环境只有他的内部函数可以访问。

   换一种说法:内部函数只有通过闭包才能访问到外部作用域

 关于闭包回收,应该是和其他对象一样,在没有被引用的情况下才会被回收。(即当内部函数被外部引用,在外部引用存活的情况下,闭包不会被回收)。

   新增的理解是,闭包是function作用域的一种(另一种为全局作用域),只有在引用的父作用域的属性时闭包才会存在,在该function生命周期over之前,父作用域的该属性也会因此被保存在内存中不会释放。

   (好吧,闭包是什么还是有疑问,但貌似是啥也不是很重要哈,了解它的特性,会用就好了,至于它到底是个啥,时间应该会告诉我的)

 

执行期还有一点需要补充的,就是new这个神奇的关键字。

 

当一个函数被普通的执行时,是这样的:

function a(){  var id = 1;       return id;}function b(){  alert(hello);}var c = a();   //return 1;var d = b();   //return underfined;//如果有返回值得情况,则返回该返回值//否则返回默认值underfined,   return; 也是返回underfined

当一个函数被特殊的执行时,是这样的:

function a(){   this.id = 1;    }a.prototype.name = "tianxia";function b(){  alert(hello);  return;}var c = new a();   //return {id:1,name:"tianxia"};var d = new b();   //return underfined;//如果在一个函数前面带上new来调用该函数,那么将创建一个隐藏连接到该函数的prototype成员的新对象,同时this将被绑定到那个新对象上。//默认返回该this对象,如果有返回值还是返回该返回值。

 

++ 作用域的声明期永远会是其父作用域的执行期

++ 函数每执行一次会产生一份'闭包',

++ 该'闭包'在没有任何引用(引用: 仍存活的子作用域)的情况下会被自动回收. 否则会一直在内存中,且只能被子作用域访问.   

ps:好吧,又是记录了一些理论的东西,上文纯属一个小菜的个人理解,如果有问题,请多多指点哈。 

 

转载于:https://www.cnblogs.com/w2154/p/4231559.html

你可能感兴趣的文章
MongoDB的简单使用
查看>>
git clone 遇到的问题
查看>>
hdfs 命令使用
查看>>
hdu 1709 The Balance
查看>>
prometheus配置
查看>>
定宽320 缩放适配手机屏幕
查看>>
BZOJ 2120 数颜色 【带修改莫队】
查看>>
【noip2004】虫食算——剪枝DFS
查看>>
Codeforces 40 E. Number Table
查看>>
CLR via C#(第3 版)
查看>>
java语法之final
查看>>
关于响应式布局
查看>>
详解ASP.Net 4中的aspnet_regsql.exe
查看>>
python 多进程和多线程的区别
查看>>
hdu1398
查看>>
[android] 网络断开的监听
查看>>
156.Binary Tree Upside Down
查看>>
MongoDB在windows下安装配置
查看>>
Upselling promotion stored procedure
查看>>
mysql编码配置
查看>>