文章部分实例和内容来自鸟哥的blogJavascript作用域原理

前端基础进阶(三):变量对象详解    波同学

在JS中,作用域的概念和其他语言差不多,是JS中一个极为重要的概念。在每次调用一个函数的时候 ,就会进入一个函数内的作用域,当从函数返回以后,就返回调用前的作用域.

理解作用域,首先理解几个概念

变量对象:执行环境(execution context)定义所有的变量和函数都存在这个对象中。虽然我们编写的代码无法访问这个对象,但是解析器在处理数据时后台会使用它

var foo=10;function func(){};//因为是在全局作用域当中,so...Global VO={foo:10,func:<function>}

 变量对象的创建经历以下几个过程:

  1. 建立arguments对象,检查上下文中的参数,建立该对象下的属性和属性值。
  2. 检查当前上下文的函数声明
  3. 检查上下文变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。

由上可以看出function的优先级比var优先级高

活动对象:在调用func的时候, 会创建一个活动对象(假设为aObj, 由JS引擎预编译时刻创建, 后面会介绍),并创建arguments属性

function foo(x,y){var z=30;function bar(){};}foo(10,20);//当执行到foo(10,20)时即会产生AOActivation Object={z:30,x:10,y:20,bar:<function>,arguments:{0:10,1:20,length:2}}

 

 注意到, 因为函数对象的[[scope]]属性是在定义一个函数的时候决定的, 而非调用的时候, 所以如下面的例子

var name = 'laruence';function echo() {alert(name);}function env() {var name = 'eve';echo();}env();

  结果

laruence

 可以看出一段函数被激活时有两个阶段,一个是创建阶段,一种执行阶段

1.生成变量对象                                 1.变量赋值

创建阶段 ==》2.建立作用域        =====》执行==》2.函数引用  ===》出栈 回收

3.确定this的指向                                3.执行代码

看下面梨字

// demo01
function test() {console.log(a);console.log(foo());var a = 1;function foo() {return 2;}
}test();

  从上下文开始理解,全局作用域的运行test()时,test()的执行上下文开始创建。

创建过程
testEC = {// 变量对象VO: {},scopeChain: {},this: {}
}// 因为本文暂时不详细解释作用域链和this,所以把变量对象专门提出来说明// VO 为 Variable Object的缩写,即变量对象
VO = {arguments: {...},  //注:在浏览器的展示中,函数的参数可能并不是放在arguments对象中,这里为了方便理解,我做了这样的处理foo: <foo reference>  // 表示foo的地址引用a: undefined
}

  变量对象和活动对象是一种对象,只不过是处于执行上下文的不同生命周期。

// 执行阶段
VO ->  AO   // Active Object
AO = {arguments: {...},foo: <foo reference>,a: 1
}

  因此demo1变成了如下代码

function test() {function foo() {return 2;}var a;console.log(a);console.log(foo());a = 1;
}test();

  实际的例子:

function factory(){var name="laruence";var intro=function(){console.log("I'm "+name);}return intro;
}
function app(para){var name=para;var func=factory();func();
}app("eve");

  当调用app的时候, scope chain是由: {window活动对象(全局)}->{app的活动对象} 组成.

此时的scope chain如下:

[[scope chain]]=[
Active Object={this:window,arguments:{0:"eve",length:1}name:'eve'func:<function>para:"eve",
},
Global VO={this:window,app:<function>,window:<object>,document:<object>
}
]

  

  当调用进入factory的函数体的时候, 此时的factory的scope chain为:

[[scope chain]]={
Active Object={this:window,arguments:{},name:"laruence",intro:<function>,
},
Global Object(Variable Object)={this:window,factory:<function>,app:<function>,window:<object>,document:<object>
}
}

  在定义intro函数的时候,intro函数[[scope]]为:

[[scope chain]]={
Object={name:"laruence",intro:<function>,this:<factory>,     //注意这里的this指向arguments:{}
},
Gloabal Object={this:window,factory:<function>,document:<object>,window:<object>
}
}

  从factory函数返回后,在app体内调用intro时,发生了标识符的解析,而此时的scope chain是:

[[scope chain]]={intro AO={<intro 活动对象>} ,Factory AO={name:"laruence",intro:<function>,},Global VO={this:window,factory:<function>,document:<obeject>,window:<object>}
}

  因为scope chain中,并不包含factory活动对象. 所以, name标识符解析的结果应该是factory活动对象中的name属性, 也就是’laruence’.

转载于:https://www.cnblogs.com/meng2017/p/8167623.html

JavaScript作用域学习笔记相关推荐

  1. JavaScript作用域学习笔记(ife2015spring学习心得)

    本文参照以下两位前辈的文章,加上自己的见解,有错误之处还望大家指出 鸟哥:Javascript作用域原理 理解 JavaScript 作用域和作用域链 为什么要理解作用域 初学js便听人说这门语言作用 ...

  2. JavaScript闭包学习笔记

    闭包(closure)是JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于JavaScript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  3. Javascript入门学习笔记

    JS入门学习笔记目录 1.JS简介 2.组成部分 3.特点 4.作用 5.JS三种添加方式 6.变量 7.数据类型 8.检测数据类型 9.逗号运算符 10.算术运算符 11.关系运算符 12.逻辑运算 ...

  4. Java Web--HTML、CSS、JavaScript详细学习笔记(内含丰富示例代码)

    ** Java Web–HTML.CSS.JavaScript学习笔记 ** HTML(Hyper Text Markup Language超文本标记语言):控制的是页面的内容,是由标签组成的语言,能 ...

  5. javascript深入浅出——学习笔记(六种数据类型和隐式转换)

    在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容?随时补充 课程大纲 1.数据类型 2.表达式和运算符 3.语句 4. ...

  6. javascript面向对象学习笔记(一)——继承

    最近在学习html5,玩了下canvas,发现js中很多的东西都不太记得了.翻了下笔记后发现还是去图书馆逛逛把,到借阅区找了我一直想看的<javascript design patterns&g ...

  7. 前端JavaScript的学习笔记

    前端知识体系 想要成为真正的"互联网Java全栈工程师"还有很长的一段路要走,其中前端是绕不开的一门必修课.本阶段课程的主要目的就是带领Java后台程序员认识前端.了解前端.掌握前 ...

  8. JavaScript Reflect 学习笔记

    今天我们来学习JavaScript中的反射和ES6的Reflect对象. 什么是反射? 反射机制是指在程序运行期间能够获取自身的信息,比如一个对象能够在运行时就知道自己有哪些属性和方法. 在ES6之前 ...

  9. JavaScript红皮书学习笔记

    1.什么是javaScript JavaScript 历史回顾 JavaScript 是什么(实现) ​ JavaScript 是一门用来与网页交互的脚本语言,包含以下三个组成部分. ​ ECMASc ...

最新文章

  1. 设计模式复习-命令模式
  2. Wpf体系结构的学习
  3. 一个设计反模式——究竟什么是轮子理论
  4. Spring+SpringMVC +MyBatis整合配置文件案例66666
  5. [scikit-learn 机器学习] 7. 朴素贝叶斯
  6. spark sql读取hive底层_[大数据]spark sql读写Hive数据不一致
  7. Angular启动过程介绍
  8. js数组去重的四种方式
  9. B - 吉哥系列故事——完美队形II HDU - 4513 (马拉车)
  10. android 圆形自定义进度条,Android自定义漂亮的圆形进度条
  11. Pyhton词云示例(移植-情人节专用版)
  12. DZ先生怪谈国标28181-2016之目录查询
  13. DS1302的电子万年历_51单片机,年月日、星期、时分秒、农历和温度,带闹钟,全套资料
  14. 正则表达式,判断输入的字符串是否只包含数字、字母、下划线三种随机组合,字符串可以包含一个或多个空格但头尾不能为空格,全为空格组成等限定字符串格式规则
  15. C++中如何判断一个字符串中包含另一个字符串
  16. 我的Android进阶之旅------gt;/storage/sdcard0, /sdcard, /mnt/sdcard ,/storage/emulated/legacy 的区别...
  17. mt6631 BT /无线/ GPS /调频 设计的通知
  18. 开源项目推荐:推荐5款前端的开源项目,vue、uniapp、react学无止境用无止境_
  19. 解决javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V异常
  20. 【学习进度】截至2022.9.6,已学习的C++知识

热门文章

  1. 组合查询——怎样使用窗口的继承达到事半功倍?
  2. delphi公共函数 UMyPubFuncFroc--版权所有 (C) 2008 勇者工作室
  3. jQuery Tags Input Plugin(添加/删除标签插件)
  4. Dynamips与VMware配合搭建网络实验环境
  5. 跨平台开发Flutter初体验
  6. OSS控制台集成将数据库实时备份到OSS的功能
  7. Java常用消息队列原理介绍及性能对比
  8. Bzoj2555 SubString
  9. 投票系统之防止重复投票
  10. POJ 1989 贪心