- 浏览: 681555 次
- 性别:
- 来自: 深圳
-
文章分类
最新评论
-
zhouyicang:
为嘛人气不够,这么好的文章,我找了几十篇博客,才找到这篇解惑了 ...
HTML 块级元素/内联元素 -
young7:
不错,解惑了
HTML 块级元素/内联元素 -
lvjin948:
获取浏览器语言的完美方案。http://blog.csdn.n ...
JavaScript获取浏览器语言类型 -
tarena_hhh:
我用了css优化工具,发现他的顺序有很大不一样?????
CSS属性书写顺序及命名规则 -
deng131:
谢谢你的提醒,是有个地方写错了
javascript事件绑定addEventListener,attachEvent
转自:http://ued.sohu.com/article/204
关于js的作用域链,早有耳闻,也曾看过几篇介绍性的博文,但一直都理解的模棱两可。近日又精心翻看了一下《悟透Javascript》这本书,觉得写得太深刻,在“代码的时空”一节里有一段介绍作用域链的地方寥寥数语,回味无穷(其实还是理解的模棱两可^_^)。现在整理下自己的读书笔记,顺便借鉴网上资源,写下来。
一、从一个简单的问题说起
下面的js代码在页面中运行显示什么结果:
JavaScript代码
1. var arg = 1;
2. function fucTest(arg) {
3. alert(arg);
4. var arg = 2;
5. //alert(arg);
6. }
7. fucTest(10);
您的答案是什么?没错,就是弹出10。我的理解是这样的,funTest函数有一个形参arg,funTest函数传入实参10,alert方法把 10弹出就是了,囧。
好,问题又来了:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. alert(arg);
4. var arg = 2;
5. }
6. arg = 10;
7. funcTest();
答案是什么?如果是5年前的我,肯定不会再往下想了,还是10!这么简单的问题还用想什么呀?我的理解是这样的:funTest函数是一个无参数的函数,函数内部通过alert方法,调用外部(全局)的变量arg,在函数执行前,arg赋值为10,弹出arg值后改变arg值为2,所以弹出值为 10。
真的是10吗?是还是不是?
测试的结果:弹出“undefined”,瀑布汗.
二、理解作用域链,从javascript运行机制说起
1、js的运行顺序
如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是:
步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)
步骤2. 做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤5
步骤3. 对var变量和function定义做“预解析”(永远不会报错的,因为只解析正确的声明)
步骤4. 执行代码段,有错则报错(比如变量未定义)
步骤5. 如果还有下一个代码段,则读入下一个代码段,重复步骤2
步骤6. 结束
上面的分析已经足够清楚,步骤二、三和步骤四里的红色字体可能是我们新手理解上的一个盲点,尤其是步骤三的“预解析”,如果不清楚什么叫预解析,总觉得不踏实。而步骤四的“有错则报错”也是经常碰到的。举例来说:
JavaScript代码
1. function funcTest() {
2. alert(arg);
3. var arg = 2;
4. }
5. funcTest();
上面这段代码执行时,弹出“undefined”,也就是说arg没有定义,js的变量不是不用定义也可以吗?
2、语法分析和“预解析”
(1)、从解释型语言的编译过程说起
众所周知,javascript是解释型语言,它不同于c#和java等编译型语言。对于传统编译型语言来说,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成;但对于解释型语言来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。
a、词法分析
简单地说,词法分析是将字符流(char stream)转换为记号流(token stream)。
但是这个转换过程并不是可以用一句话就可以概括的那么简单,我们可以试着用伪代码理解一段简单的程序:
代码var result=x-y;的转换大致可以表示如下:
NAME "result"
EQUALS
NAME "x"
MINUS
NAME "y"
SEMICOLON
b、语法分析
简单地说,语法分析就是为了构造合法的语法分析树,而语法分析树可以直观地表示出推导的过程。
那么什么是语法分析树?简单地说,就是程序推导过程的描述。但是到底什么是语法树,请参考专业文章,本篇略过。
c、其他
通过语法分析,构造出语法分析树后,接下来还可能需要进一步的语义检查。对于传统强类型语言来说,语义检查的主要部分是类型检查,比如函数的实参和形参类型是否匹配等等。
结论:通过上面的分析可以看出,对于javascript引擎来说,肯定有词法分析和语法分析,之后可能还有语义检查、代码优化等步骤,等这些编译步骤完成之后(任何语言都有编译过程,只是解释型语言没有编译成二进制代码),才会开始执行代码。
(2)、执行过程
a、javascript的作用域机制
通过编译,javascript代码已经翻译成了语法树,然后会立刻按照语法树执行。
进一步的执行过程,需要理解javascript的作用域机制:词法作用域(lexcical scope)。通俗地讲,就是javascript变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,编译器通过静态分析就能确定,因此词法作用域也叫做静态作用域(static scope)。但需要注意,with和eval的语义无法仅通过静态技术实现,所以只能说javascript的作用域机制非常接近词法作用域(lexical scope).
javascript引擎在执行每个函数实例时,都会创建一个执行环境(execution context)。执行环境中包含一个调用对象(call object), 调用对象是一个scriptObject结构(scriptObject是与函数相关的一套静态系统,与函数实例的生命周期保持一致),用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析结构(注意varDecls和 funDecls等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到scriptObject上)。
b、javascript作用域机制的实现方法
词法作用域(lexical scope)是javascript的作用域机制,还需要理解它的实现方法,就是作用域链(scope chain)。作用域链是一个name lookup机制,首先在当前执行环境的scriptObject中寻找,没找到,则顺着upvalue到父scriptObject中寻找,一直 lookup到全局调用对象(global object)。
现在回过头来分析第二个问题:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. alert(arg);
4. var arg = 2;
5. }
6. arg = 10;
7. funcTest();
在执行funcTest函数时,也即进入了funcTest对应的作用域,js引擎在执行时,当遇到对变量名或者函数名的使用时,会首先在当前作用域(也即funcTest对应的作用域)查找变量或者函数(显然,arg变量在funcTest对应的作用域里被定义为var arg=2 所以alert方法的参数采用的是当前作用域的arg,但是因为arg被定义在alert方法后,所以arg变量默认值为undefined)。当然,如果没有找到就到上层作用域查找,依此类推(作用域范围可以持续到javascript运行环境的根:window对象)。
最后,让你看的更清楚,上面的代码其实可以等价于:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. var arg; //默认值undefined
4. alert(arg);
5. arg = 2;
6. }
7. arg = 10;
8. funcTest();
c、闭包(closure)
当一个函数实例执行时,会创建或关联到一个闭包。 (关于闭包,打算另写一篇学习笔记)
scriptObject用来静态保存与函数相关的变量表,闭包则在执行期动态保存这些变量表及其运行值;
闭包的生命周期有可能比函数实例长。函数实例在活动引用为空后会自动销毁;
闭包则要等要数据引用为空后,由javascript引擎回收(有些情况下不会自动回收,就导致了内存泄漏)。
ps:关于“执行过程”这一段比较拗口,名词很多,不过别被它们吓住,一旦理解了执行环境(execution context)、调用对象(call object)、词法作用域(lexical scope)、作用域链(scope chain)、闭包(closure)等这些概念,javascript的很多现象都能迎刃而解。
JavaScript 中的作用域链Scope Chain
<script type="text/javascript">
/*
作用域链(Scope Chain)
JavaScript中的一种重要机制,JS中所有的标识符(Identifier)都是通过Scope Chain来查找值的。
*/
var i = "w i";
/*
词法作用域(Lexical Scoping)
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.
这个作用域我们称之为[[scope]]
非内嵌函数的[[scope]]都是宿主对象,不同的宿主会有不同的内容
*/
var a =function(){
alert(i);
}
var b = function(){
var i = "b i";
a();
}
var c = function(){
a();
}
a();
/*
函数在运行的时候,会先创建一个call Object,
将函数的形参、变量和函数声明的结果都添加到call Object作为属性;
把call Object添加到该函数的作用域链的最前面;
然后,再将函数定义时的[[scope]]添加到它的作用域链中;
函数体内的标识符查找
先从Scope Chain中第一个对象找,存在则返回,否则
继续查找下一个对象,存在则返回,否则(重复此步骤)
最后找不到则返回undefined
*/
b();
c();
/*
JavaScript中的scope Chain的机制使得闭包得以实现
*/
var d = function(){
var i = "d i";
var e = function(){
alert(i);
}
return e;
}
var f = d();
f();
/*
f是function e的引用
call Object部分:没有形参、变量声明和内部函数;
[[scope]]部分:e定义在函数d体内,e的[[scope]]中可以访问到d,i,e,然后d也会有一个[[scope]],又可以接着往上访问,这样,便形成一条链
*/
</script>
具名函数表达式与匿名函数表达式和函数申明的区别
<script type="text/javascript">
/*
具名函数表达式与匿名函数表达式和函数申明的区别
winter:
正常的函数定义时是直接把[[scope]]设为定义时的scope chain
但是具名函数表达式是先给scope chain加入一个new Object
之后再将[[scope]]设为新的scope chain
设完后再将[[scope]]还原到正常函数定义时的[[scope]]
等于是在正常函数定义时的[[scope]]添加了一个new Object到最前面
在不同浏览器中对具名函数表达式的处理方式都太一样,都没太按ECMAScript中的规定去实现
ECMAScript中关于具名函数表达式实现的规定大致如下:
1、创建一个new Object
2、将这个new Object插入到scope chain
3、创建一个new Function,将scope chain设为[[scope]]
4、为new Object添加一个属性,function name:function body(readOnly、don't Delete)
5、移除new Object
6、返回Function
*/
var test="wrong"
Object.prototype.test="right";
var f = function(){
alert(test);
}
f();
/*
正常函数申明运行时的作用域链
call Object
[[scope]]
*/
var f1 = function f0(){
alert(test);
}
f1();
/*
具名函数表达式运行时的作用域链
call Object
new Object
[[scope]]
*/
</script>
关于js的作用域链,早有耳闻,也曾看过几篇介绍性的博文,但一直都理解的模棱两可。近日又精心翻看了一下《悟透Javascript》这本书,觉得写得太深刻,在“代码的时空”一节里有一段介绍作用域链的地方寥寥数语,回味无穷(其实还是理解的模棱两可^_^)。现在整理下自己的读书笔记,顺便借鉴网上资源,写下来。
一、从一个简单的问题说起
下面的js代码在页面中运行显示什么结果:
JavaScript代码
1. var arg = 1;
2. function fucTest(arg) {
3. alert(arg);
4. var arg = 2;
5. //alert(arg);
6. }
7. fucTest(10);
您的答案是什么?没错,就是弹出10。我的理解是这样的,funTest函数有一个形参arg,funTest函数传入实参10,alert方法把 10弹出就是了,囧。
好,问题又来了:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. alert(arg);
4. var arg = 2;
5. }
6. arg = 10;
7. funcTest();
答案是什么?如果是5年前的我,肯定不会再往下想了,还是10!这么简单的问题还用想什么呀?我的理解是这样的:funTest函数是一个无参数的函数,函数内部通过alert方法,调用外部(全局)的变量arg,在函数执行前,arg赋值为10,弹出arg值后改变arg值为2,所以弹出值为 10。
真的是10吗?是还是不是?
测试的结果:弹出“undefined”,瀑布汗.
二、理解作用域链,从javascript运行机制说起
1、js的运行顺序
如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是:
步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)
步骤2. 做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤5
步骤3. 对var变量和function定义做“预解析”(永远不会报错的,因为只解析正确的声明)
步骤4. 执行代码段,有错则报错(比如变量未定义)
步骤5. 如果还有下一个代码段,则读入下一个代码段,重复步骤2
步骤6. 结束
上面的分析已经足够清楚,步骤二、三和步骤四里的红色字体可能是我们新手理解上的一个盲点,尤其是步骤三的“预解析”,如果不清楚什么叫预解析,总觉得不踏实。而步骤四的“有错则报错”也是经常碰到的。举例来说:
JavaScript代码
1. function funcTest() {
2. alert(arg);
3. var arg = 2;
4. }
5. funcTest();
上面这段代码执行时,弹出“undefined”,也就是说arg没有定义,js的变量不是不用定义也可以吗?
2、语法分析和“预解析”
(1)、从解释型语言的编译过程说起
众所周知,javascript是解释型语言,它不同于c#和java等编译型语言。对于传统编译型语言来说,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成;但对于解释型语言来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。
a、词法分析
简单地说,词法分析是将字符流(char stream)转换为记号流(token stream)。
但是这个转换过程并不是可以用一句话就可以概括的那么简单,我们可以试着用伪代码理解一段简单的程序:
代码var result=x-y;的转换大致可以表示如下:
NAME "result"
EQUALS
NAME "x"
MINUS
NAME "y"
SEMICOLON
b、语法分析
简单地说,语法分析就是为了构造合法的语法分析树,而语法分析树可以直观地表示出推导的过程。
那么什么是语法分析树?简单地说,就是程序推导过程的描述。但是到底什么是语法树,请参考专业文章,本篇略过。
c、其他
通过语法分析,构造出语法分析树后,接下来还可能需要进一步的语义检查。对于传统强类型语言来说,语义检查的主要部分是类型检查,比如函数的实参和形参类型是否匹配等等。
结论:通过上面的分析可以看出,对于javascript引擎来说,肯定有词法分析和语法分析,之后可能还有语义检查、代码优化等步骤,等这些编译步骤完成之后(任何语言都有编译过程,只是解释型语言没有编译成二进制代码),才会开始执行代码。
(2)、执行过程
a、javascript的作用域机制
通过编译,javascript代码已经翻译成了语法树,然后会立刻按照语法树执行。
进一步的执行过程,需要理解javascript的作用域机制:词法作用域(lexcical scope)。通俗地讲,就是javascript变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,编译器通过静态分析就能确定,因此词法作用域也叫做静态作用域(static scope)。但需要注意,with和eval的语义无法仅通过静态技术实现,所以只能说javascript的作用域机制非常接近词法作用域(lexical scope).
javascript引擎在执行每个函数实例时,都会创建一个执行环境(execution context)。执行环境中包含一个调用对象(call object), 调用对象是一个scriptObject结构(scriptObject是与函数相关的一套静态系统,与函数实例的生命周期保持一致),用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析结构(注意varDecls和 funDecls等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到scriptObject上)。
b、javascript作用域机制的实现方法
词法作用域(lexical scope)是javascript的作用域机制,还需要理解它的实现方法,就是作用域链(scope chain)。作用域链是一个name lookup机制,首先在当前执行环境的scriptObject中寻找,没找到,则顺着upvalue到父scriptObject中寻找,一直 lookup到全局调用对象(global object)。
现在回过头来分析第二个问题:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. alert(arg);
4. var arg = 2;
5. }
6. arg = 10;
7. funcTest();
在执行funcTest函数时,也即进入了funcTest对应的作用域,js引擎在执行时,当遇到对变量名或者函数名的使用时,会首先在当前作用域(也即funcTest对应的作用域)查找变量或者函数(显然,arg变量在funcTest对应的作用域里被定义为var arg=2 所以alert方法的参数采用的是当前作用域的arg,但是因为arg被定义在alert方法后,所以arg变量默认值为undefined)。当然,如果没有找到就到上层作用域查找,依此类推(作用域范围可以持续到javascript运行环境的根:window对象)。
最后,让你看的更清楚,上面的代码其实可以等价于:
JavaScript代码
1. var arg = 1;
2. function funcTest() {
3. var arg; //默认值undefined
4. alert(arg);
5. arg = 2;
6. }
7. arg = 10;
8. funcTest();
c、闭包(closure)
当一个函数实例执行时,会创建或关联到一个闭包。 (关于闭包,打算另写一篇学习笔记)
scriptObject用来静态保存与函数相关的变量表,闭包则在执行期动态保存这些变量表及其运行值;
闭包的生命周期有可能比函数实例长。函数实例在活动引用为空后会自动销毁;
闭包则要等要数据引用为空后,由javascript引擎回收(有些情况下不会自动回收,就导致了内存泄漏)。
ps:关于“执行过程”这一段比较拗口,名词很多,不过别被它们吓住,一旦理解了执行环境(execution context)、调用对象(call object)、词法作用域(lexical scope)、作用域链(scope chain)、闭包(closure)等这些概念,javascript的很多现象都能迎刃而解。
JavaScript 中的作用域链Scope Chain
<script type="text/javascript">
/*
作用域链(Scope Chain)
JavaScript中的一种重要机制,JS中所有的标识符(Identifier)都是通过Scope Chain来查找值的。
*/
var i = "w i";
/*
词法作用域(Lexical Scoping)
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.
这个作用域我们称之为[[scope]]
非内嵌函数的[[scope]]都是宿主对象,不同的宿主会有不同的内容
*/
var a =function(){
alert(i);
}
var b = function(){
var i = "b i";
a();
}
var c = function(){
a();
}
a();
/*
函数在运行的时候,会先创建一个call Object,
将函数的形参、变量和函数声明的结果都添加到call Object作为属性;
把call Object添加到该函数的作用域链的最前面;
然后,再将函数定义时的[[scope]]添加到它的作用域链中;
函数体内的标识符查找
先从Scope Chain中第一个对象找,存在则返回,否则
继续查找下一个对象,存在则返回,否则(重复此步骤)
最后找不到则返回undefined
*/
b();
c();
/*
JavaScript中的scope Chain的机制使得闭包得以实现
*/
var d = function(){
var i = "d i";
var e = function(){
alert(i);
}
return e;
}
var f = d();
f();
/*
f是function e的引用
call Object部分:没有形参、变量声明和内部函数;
[[scope]]部分:e定义在函数d体内,e的[[scope]]中可以访问到d,i,e,然后d也会有一个[[scope]],又可以接着往上访问,这样,便形成一条链
*/
</script>
具名函数表达式与匿名函数表达式和函数申明的区别
<script type="text/javascript">
/*
具名函数表达式与匿名函数表达式和函数申明的区别
winter:
正常的函数定义时是直接把[[scope]]设为定义时的scope chain
但是具名函数表达式是先给scope chain加入一个new Object
之后再将[[scope]]设为新的scope chain
设完后再将[[scope]]还原到正常函数定义时的[[scope]]
等于是在正常函数定义时的[[scope]]添加了一个new Object到最前面
在不同浏览器中对具名函数表达式的处理方式都太一样,都没太按ECMAScript中的规定去实现
ECMAScript中关于具名函数表达式实现的规定大致如下:
1、创建一个new Object
2、将这个new Object插入到scope chain
3、创建一个new Function,将scope chain设为[[scope]]
4、为new Object添加一个属性,function name:function body(readOnly、don't Delete)
5、移除new Object
6、返回Function
*/
var test="wrong"
Object.prototype.test="right";
var f = function(){
alert(test);
}
f();
/*
正常函数申明运行时的作用域链
call Object
[[scope]]
*/
var f1 = function f0(){
alert(test);
}
f1();
/*
具名函数表达式运行时的作用域链
call Object
new Object
[[scope]]
*/
</script>
发表评论
-
IE浏览器stylesheets加载资源限制问题
2015-03-08 20:30 1103@import url()做一下总结: 1:@import ... -
理解Javascript原型及继承
2012-08-15 22:13 1368js初次使用起来觉得很简单但是在使用一段时间后很不深入的理解原 ... -
JS判断IE浏览器支持版本
2012-02-01 19:00 3007/* * @description 判断是否是IE,返回具体 ... -
jsonp动态创建script方式IE9问题
2012-02-01 16:28 2449在IE9浏览器创建一个script元素,然后指定其src属性u ... -
IE9下使用jsonp方式调用问题
2012-01-31 19:03 23141. 如果JSONP返回的Content-Type不符合规范, ... -
JavaScript获取浏览器语言类型
2011-12-31 18:24 7866获取浏览器语言: IE: navigator.browser ... -
IE Security Comprehensive Protection
2011-12-19 20:14 1797IE浏览器安全方面的处理,本人英文不好建议大家直接看英文: ... -
javaScript 中比较数字字符串问题
2011-10-10 21:49 4711在实现前端页面排序功能过程中遇到的问题,由于自己的粗心导致了生 ... -
javascript设置label标签 for属性
2011-09-11 10:36 3634js创建label标签的for属性用来增加操作响应区域。 v ... -
javascript事件绑定addEventListener,attachEvent
2011-07-31 18:55 3589为了考虑浏览器的兼容性问题,都需要对浏览器进行类型检测。 f ... -
readyState五种状态详解
2011-07-24 14:15 1664(0) UNINITIALIZED 未初始化 The obje ... -
getElementByTagName 与 querySelectorAll
2011-07-14 11:29 1518虽然网上有中文翻译但是还是直接看英文有感觉。getElemen ... -
拖放 Drag and drop 方法
2011-07-10 18:55 1554虽然网上又很多实现方法,但是还是需要理解拖放原理。通过绑定on ... -
闭包传入参数 window & undefined
2011-07-03 08:53 2344大家在前端开发中对闭包应该和熟悉了,也就是几种常见的闭包方式: ... -
textarea光标位置插入文字
2011-06-18 18:14 2157各浏览器TextArea获得焦点后的光标位置情况: text ... -
IE6上Array不支持indexOf方法
2011-06-06 10:17 2275在IE6不支持Array上indexOf方法,又是可恶的ie, ... -
处理不支持JavaScript脚本情况
2011-05-26 10:24 1368现在主流的浏览器都支持javascrip, 但还是有小部分不支 ... -
动态创建iframe设置属性name问题
2011-04-20 13:54 2771通常iframe的name可以是link或者form的targ ... -
WebSocket and Socket.IO
2011-04-06 15:39 3512WebSocket API是下一代客户端-服务器的异步通信方法 ... -
Preload CSS/JavaScript预加载
2011-04-06 10:20 1523希望达到效果是页面第一次载入以后,如果在次刷新页或者进入下一个 ...
相关推荐
### JavaScript作用域链(Scope Chain)初探 #### 一、引言 JavaScript的作用域链是一个重要的概念,尤其是在深入理解JavaScript执行机制时不可或缺的一部分。本文将通过对几个具体例子的分析来探讨JavaScript作用域...
JavaScript 作用域链是 JavaScript 语言中一个至关重要的概念,它决定了变量和函数的访问权限。在 JavaScript 中,每个函数都有自己的作用域,也就是变量和函数的可见范围。当一个函数被创建时,它会形成一个作用域...
二、作用域(Scope)和作用域链(Scope Chain) 在 JavaScript 中,每个执行环境都有一个 Variable Object,用于存储变量和函数。函数体中可以使用全局变量、函数嵌套定义时情况更复杂点。这些情况下怎样处理?...
-作用域链(Scope Chain):由多个变量对象组成,用于变量查找。 函数作用域是词法作用域(Lexical Scoping),意味着函数的作用域在函数定义的时候就确定了。函数中使用的变量会首先在本函数的作用域中查找,如果...
作用域链(Scope Chain): 当JavaScript引擎试图查找变量时,它会遵循一个称为作用域链的规则。这个链是从当前执行环境(可能是函数内部)开始,逐级向上搜索,直到找到全局作用域。如果在当前作用域找不到变量,就...
JavaScript作用域和作用域链是JS编程中非常核心的概念,理解这些概念对于编写可预测和高效的代码至关重要。首先,让我们来探讨JavaScript中的作用域。 一、JavaScript作用域 在JavaScript中,作用域决定了变量和...
接下来,我们要讨论的是作用域链(Scope Chain): - 每个函数都有一个内部属性`[[Scope]]`,它包含了函数创建时作用域内的对象集合。 - 当函数执行时,`[[Scope]]`会被用来创建一个执行期上下文,其中的作用域链...
这些作用域形成了一个作用域链(Scope Chain),子作用域可以访问父作用域的属性,但反之则不行。除了使用这些内置指令创建作用域之外,AngularJS还提供了API来手动创建新的作用域实例。 数据绑定是AngularJS的一个...
现在来谈谈**作用域链(Scope Chain)**: 当在函数内部访问一个变量时,JavaScript会先在当前作用域查找,如果没有找到,则向上一级父作用域查找,直到找到全局作用域。如果仍然没有找到,就会抛出错误。这个查找...
3. **作用域链(Scope Chain)**:当函数被调用时,JavaScript引擎会创建一个作用域链,它由当前活动对象和函数定义时的作用域链组成,用于确定变量的查找顺序。 **作用域链的创建与使用:** 1. **全局作用域链**:...
4. **作用域链(Scope Chain)** - 每个执行上下文(全局或函数)都有一个与之关联的作用域链,它决定了变量查找的顺序。作用域链由当前执行上下文的变量对象(VO或AO)和所有包含的父级执行上下文的变量对象组成,...
##### 3.2 作用域链(Scope Chain) 为了支持词法作用域,JavaScript引擎使用了一种名为作用域链的数据结构。作用域链是一个对象数组,每个对象代表一个作用域。当查找变量时,JavaScript引擎会从当前作用域开始,...
**作用域链**(Scope Chain)是另一个关键概念,它涉及到查找变量的过程。当尝试访问一个变量时,JavaScript会首先在当前作用域中查找。如果找不到,它会向上遍历作用域链,直到找到该变量或者到达全局作用域。如果...
2. **初始化作用域链**:该上下文的作用域链(Scope Chain)会被初始化为函数的`[[Scope]]`集合中的成员。`[[Scope]]`集合包含了一个或多个对象,这些对象定义了函数可以访问的外部环境。 3. **创建激活对象**:接...
在JavaScript编程中,作用域链是一个非常重要的概念,它涉及到变量的查找规则和作用域的层次结构。这个压缩包文件“scope-chain.rar”显然是为了帮助理解这一核心概念。通过分析其中的“用一段代码来解释JavaScript...
JavaScript中的执行环境(Execution Context)和作用域链(Scope Chain)是理解JavaScript变量访问规则和作用范围的关键概念。执行环境定义了代码运行时的上下文,它规定了变量和函数的可访问性。每个JavaScript代码...
闭包的形成基于两个关键概念:作用域链(Scope Chain)和执行上下文(Execution Context)。 1. **作用域链**: - 在每个函数创建时,都会构建一个作用域链,用于存储函数可以访问的所有变量和函数。 - 作用域链...