1.5.6函数作用域

Posted aorange

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.5.6函数作用域相关的知识,希望对你有一定的参考价值。

1.5.6 函数作用域

1.作用域   定义变量并能找到变量的规则

在函数里面中可以使用全局变量在全局中不能够使用函数中的变量

技术图片             技术图片

js中 变量有两个存放的区域

 

1.全局作用域:

全局变量会自动成为window对象的属性

window对象也可以叫做Global Object GO对象

打开浏览器 自动生成window对象,即生成GO对象

关闭浏览器 window对象就自动销毁了

eg:当打开浏览器的时候,会自动生成GO对象,会自动把变量名生成GO对象的属性名,变量名的值会变成GO对象的属性值,上图的auto不在花括号内,所以是全局变量

函数表达式也可以放到全局变量中

GO   属性名:属性值

c:‘heaven‘,

auto:function(),

heaven:function()

 

 

2.函数作用域

函数的预编译四部曲:  /* 函数执行时,会生成一个AO对象,活动的*/

①创建AO对象 ==> Activated Object(活动对象)  

找到形参和变量,把形参和变量作为AO对象的属性名,值是undefined

把实参的值赋给形参。此时不再是undefined

④在函数中找到函数声明,把函数名作为AO对象的属性名,值是函数体。

 

预编译之后才能执行JS代码  函数执行后必然生成自己的AO对象,函数执行完后被销毁

 

全局的预编译三步:

1.创建GO对象 ==> Global Object(GO对象)

2.找到变量,把变量作为GO对象的属性名,值是undefined

3.在全局中找到函数声明,把函数名作为GO对象的属性名,值是函数体

开始执行代码

函数表达式也可以放到全局变量中

预编译练习:
function outer()
/*
* AO
* b:3,
* inner:function()
* 
* */
function inner()
/*
* AO
* a:4
* 
* */
var a = 4;
c = 5; //一个变量 没有var关键词,直接赋值,则这个是全局的,叫做暗示全局变量
console.log(a); //4 inner的AO中找到变量a
console.log(b); //3 outer的AO中找到变量b
console.log(c); //5 GO中找到变量c

var b = 3;
inner();

outer();
var a = 2;
console.log(outer);

找变量的时候,先找里面,再找外面

函数里面var a=4;先是走第二步,a:undefind,之后再变成a=3,打印的时候会从AO对象里面找

 

3.变量提升:预编译时,从上往下,第一句是打印,第二句是定义,则打印出是undefined var b 所以被提升   

技术图片

 

 

4.作用域链

console.dir()下的函数的[[Scopes]]这个属性 存放在函数的作用域链

技术图片

 

 

inner函数未执行(死函数)

--->inner函数的作用域链 = outer:AO+GO  (就是不算技术图片的时候)

 

inner() -->inner函数执行(激活的函数)

--->inner函数的作用域链 = inner:AO + outer:AO + GO 技术图片执行时)

 

所以a在当前的函数里面找不到,会顺着作用链找,就是从内部往上找

 

outer函数未执行

--->outer函数的作用域链 = GO  (outer所在的环境是GO)

outer()函数执行

--->outer函数的作用域链 = outer:AO + GO

 

例子

技术图片

 

 GO: autofunction()

 

 AO:  b:undefined

 

  a:undefined     然后执行第四不步,找到函数声明

 

  b:function()    所以上面的b被覆盖了

 

所以b打印出来的是一个函数,往上找

 

GO
a:2
auto:function()
AO
a:undefined 没有实参不执行第三步骤
没有函数声明

var a =2
function auto(a)
if(typeof a) //所以a是undefined 
console.log("海文"); //type(undefined)== "undefined"
else //转换为布尔值是true
console.log("heaven");

var a;

auto();

 

5.闭包

当内部函数被保存在外部时,由于内部函数的作用域链上存在内部函数创建时的环境(即父级函数和祖先函数的AO对象,全局对象GO),导致内部函数可以顺着作用域链寻找变量,所以形成了闭包,同时内部函数的作用域链上(即父级函数和祖先函数的AO对象,全局对象GO)无法被垃圾回收机制回收,导致了内存泄漏

GOouter:function(),

  result:function inner()

outer:AO b:4

    inner:function()

    inner:AO    空   

function outer()

  var b = 3;

  function inner()    //outer:AO +GO

  b++;

  console.log(b); //4 在outer的AO中找到的

  return inner;   //是有return抛出里面的未激活函数的这样子形式叫闭包结构

  var result = outer();

  console.log(result); //打印的是inner的函数体

  result(); //让抛出来的inner函数再次执行

还有 var result = outer(); 是被提升了到GO,系统先var result,属性值是undefined, 原来的就变成 result = outer() // 不会显示出来的

 

1.5.7.函数表达式和函数声明之间的转换

函数声明转换成函数表达式的方法

在函数声明前面加上  , ~ ,+, -,把函数声明整体放置在()

重要结论:

* 1.函数表达式的名字只能在自身作用域中使用 (是会把自身函数打印出来)

! function auto()

console.log(auto);

(函数表达式是没有名字的,var a=function 这里不能有名字(),如果有名字,打印auto(),会报错,因为系统默认会把auto干掉)

* 2.只有函数表达式后面紧跟()才能执行后面()里的是用来传实参的

例子:

(function auto()

console.log(‘我被启动了‘);

)()

 

以上是关于1.5.6函数作用域的主要内容,如果未能解决你的问题,请参考以下文章

JS 作用域及作用域链

JS作用域作用域链

函数之参数作用域

JavaScript 作用域 与 作用域链

JS---闭包

JavaScript ES6 的let和const