JavaScript函数之作用域 / 作用链域 / 预解析
关于作用域和作用链域的问题,很多文章讲的都很详细,本文属于摘录自己觉得对自己有价值的部分,留由后用,仅供参考,需要查看详细信息请点击我给出的原文链接查看原文件
做一个有爱的搬运工~~
-------------------------------------------------------------------------------------------------------------------------------------------
作用域
js中作用域只有一种,就是函数作用域,除此之外,还存在一种作用域叫块作用域,但在此之前,想先说一下什么叫做块
块
在JAVA或者C中(因为我只学过这两种语言),块就是写在{}中的语句,一般看作一条语句执行,
块作用域(JS中不存在块作用域的概念)
在块中的语句对块外是封闭的,在JAVA和C中都有这样的特性
例如
//JAVA 代码
public class Block {
public static void main(String[] args) {
if(true){
int i = 9;
}
System.out.println(i);//代码报错
}
}
//以上的代码编译时会报错,强制编译并执行时会抛出以下的错误:
//Exception in thread "main" java.lang.Error: Unresolved //compilation problem: i cannot be resolved to a variable
所以,JAVA是有块作用域的概念的,同样的代码,放在JS中时
//JavaScript代码
function fun(){
if(true){
var i = 9;
}
return i;
}
fun();//输出 9
这就说明, 在if语句中声明的变量在if语句之后被保留在内存中了,并没有销毁.
需要特别说明的是:JS中,在函数中用var定义的变量是局部变量,不用var定义的变量会默认作为全局变量使用
function f1(){
var n=9;
m = 10;
}
f1();
console.log(n);//不会输出结果,报错误:ReferenceError: n is not defined, 意思是该变量未定义
console.log(m);//输出10
关于这个说法,在很多文章中都有提及,比如 Javascript中模仿块级作用域 : 其中对JS中作用域的解释说:使用var关键字声明变量时,这个变量会自动添加到距离最近的可用环境中。对于函数而言,这个最近的环境就是函数的局部环境。如果变量在未经声明的情况下被初始化,则该变量会被自动添加到全局环境。
在JS中实现块作用域的使用效果
同样在 Javascript中模仿块级作用域 这篇文章中,利用匿名函数来实现块作用域的功能
(function(){ //块级作用域 })();
//来自原文的话: 这种技术常在全局作用域中用在函数外部,来限制向全局作用域中添加过多的变量和函数。当然,只要我们临时需要一些变量,都可以使用块级作用域(私有作用域)。当匿名函数执行完毕,其作用域链立即销毁,从而可以减少闭包占用资源问题。
在这里再贴一个也比较好的说明作用域知识的文章 js作用域问题一步步透彻理解
这篇文章中,有这样一个例子(这个细节是我之前并没有注意过的>>细节指数:★★★★)
function fun(){
var a = b = 10;
}
console.log(a);//ReferenceError: a is not defined
console.log(b);//输出: 10
/*
*原文的话: var a = b = 10; 这种写法在函数内: b其实是全局变量,a当然是局部变量
*/
所以我自己给出了下面的例子
function fun(){
var a = 10, b = 10;
}
console.log(a);//ReferenceError: a is not defined
console.log(b);//ReferenceError: b is not defined
/*
*a是局部变量
*b是局部变量
*我们可以很清楚的知道, var a = 10, b = 10; 这种写法在函数内是定义局部变量的有效方法,
*/
-----------------------------------------------------------------------------------------------------------------------
作用链域
预解析(在说作用链域之前,我想先说一个问题---预解析,先给出引用的文章地址, 方便回溯)
解释一下啥叫预解析(自己起的名),希望给一些初学js的提供些帮助
说法:js引擎读取一段js代码,首先预解析(这个名字我起的),就是逐行读取js代码,寻找全局变量和全局函数,遇到全局变量,把变量的值变为undefind,存在内存中,遇到全局函数,直接存在内存中,这个过程如果发现语法错误,预解析终止。
当预解析完成后,js引擎在从第一行开始逐行运行js代码。
说法:js的预解析是在程序进入一个新的环境时,把该环境里的变量或函数预解析到它们能调用的环境中。即每一次预解析的单位是一个执行环境。
说法:函数预解析:
1、javascript在执行前会进行类似“预解析”的操作:首先会创建一个在当前执行环境下的活动对象,并将那些用var 声明的变量、定义的函数设置为活动对象的属性,但是此时这些变量的赋值都是undefined。
2、在javascript解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = …这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)。
//预处理的例子 console.log(a);//输出: undefined
console.log(b);//输出: undefined
console.log(c);//输出: function c(){return "C";} var a = "A";
var b = function(){return "B"; }
function c(){return "C";} //在语法分析阶段,a保存用var进行显示声明的局部变量,并且置默认值为undefined,这里就是上述代码中"console.log(a)"输出为undefined的原因,由于代码在语法分析阶段就已经保留了标记符a,在赋值语句"var a = "A"; "执行之前a的值都是undefined,因此在"console.log(a)"的时候就显示为undefined了。(修改引用自:(转载)浅谈JavaScript的闭包和作用域链)
至此,如果预解析的概念有所了解了(其实我还没有完全理解,疑问就是:上例中的b和c的输出结果为什么不一样???如果有人理解,可以评论告诉我,不胜感激),就可以来说说作用链域的事儿了.
作用链域
看看这篇文章: (转载)浅谈JavaScript的闭包和作用域链(这篇文章讲了很多机制性的东西,个人觉得比较好!!!)
原文:作用域链(scope chain)就是由作用域组成的链,是一个类似链状的数据结构。作用域就是对上下文环境的数据描述。闭包和作用域链是紧密关系的,函数实例执行时的闭包是构成作用域链的基本元素。JavaScript代码在执行前会进行语法分析,在语法分析阶段,会记录全局环境中的变量声明和函数定义,构造函数的调用对象(Call Oject、Activation Object、Activate Object、活动对象,不同称呼罢了)和在全局环境下的作用域链。
[ 关于闭包的内容我会在下一篇文章 JavaScript函数之闭包 中具体来说 ]
至于作用链域的其他知识点,我感觉没有办法总结的比文章(转载)浅谈JavaScript的闭包和作用域链要好,所以,不多说,看原文!
--------------------------------------------------------------------------------------------------------------------------
参考文章:
解释一下啥叫预解析(自己起的名),希望给一些初学js的提供些帮助
JavaScript函数之作用域 / 作用链域 / 预解析的更多相关文章
- JS高级---作用域,作用域链和预解析
作用域,作用域链和预解析 变量---->局部变量和全局变量, 作用域: 就是变量的使用范围 局部作用域和全局作用域 js中没有块级作用域---一对括号中定义的变量,这个变量可以在大括 ...
- [译]JavaScript:函数的作用域链
原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...
- JavaScript函数及作用域
知识内容: 1.JavaScript函数 2.JavaScript全局函数及特殊函数 3.JavaScript作用域 4.本节练习 参考资料:<JavaScript高级程序设计> 一.Ja ...
- javascript 函数和作用域(闭包、作用域)(七)
一.闭包 JavaScript中允许嵌套函数,允许函数用作数据(可以把函数赋值给变量,存储在对象属性中,存储在数组元素中),并且使用词法作用域,这些因素相互交互,创造了惊人的,强大的闭包效果.[upd ...
- JavaScript函数变量作用域
变量作用域 在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量. 如果两个不同的函数各自申明了同一变 ...
- JavaScript函数constructor的作用,意义
前几天写了一片 如何用正确的姿势编写jQuery插件 有朋友拍砖,指正.再此谢谢! 讨论:指定函数的constructor作用到底是什么? 我们一般写jQuery插件的时候是这样的: //构造函数 f ...
- function——函数声明头的提升和预解析
函数: 即function语句的集合,就是将多个语句封装到一起: 函数的执行要会自己遍历,遇见函数 a():执行语句,就要移交控制权,函数执行完毕之后,控制权又移交回来了! 函数的参数要罗列在func ...
- javascript 函数及作用域总结介绍
在js中使用函数注意三点: 1.函数被调用时,它是运行在他被声明时的语法环境中的: 2.函数自己无法运行,它总是被对象调用的,函数运行时,函数体内的this指针指向调用该函数的对象,如果调用函数时没有 ...
- javascript 函数和作用域(函数,this)(六)
重点. 一.函数 1.函数介绍 函数是一块JavaScript代码,被定义一次,但可执行和调用多次.JS中的函数也是对象,所以JS函数可以像其他对象那样操作和传递,所以我们也常叫JS中的函数为函数对象 ...
随机推荐
- 201521123088《JAVA程序设计》第8周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4 ...
- Java 第八周总结
1. 本周学习总结 2. 书面作业 1.List中指定元素的删除 1.1 实验总结 list中可以通过list.get(i)来获取具体第几个的元素的值,再通过compareTo来对比 通过in.has ...
- 201521123007《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 作业参考文件下载 1. 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.jav ...
- 201521123006 《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 本周除了继承,我们还重点学习了多态. (1)多态性在于有相同的形态,却是不同的行为或者说是不 ...
- 201521123003《Java程序设计》第1周学习总结
1. 本周学习总结 1.了解Java语言的特点: 2.明确了jdk,jre,jvm的具体含义及区别 3.掌握java的编译及运行步骤 4.了解jdk文档的用法 2. 书面作业 Q1.为什么java程序 ...
- Java程序设计——学生信息系统
1.团队课程设计博客链接 http://www.cnblogs.com/YYYYYYY/p/7065278.html 2.个人负责模块说明 2.1 管理界面 2.2 清空:单击清空键,可清空数据栏 2 ...
- PHP面向对象三大特性之一:封装
面向对象的三大特性:封装.继承.多态 1.封装 封装的目的:让类更加安全,做法是不让外界直接访问类的成员 具体做法:1.成员变为私有:访问修饰符(public.private.protected) ...
- 04面向对象编程-02-原型继承 和 ES6的class继承
1.原型继承 在上一篇中,我们提到,JS中原型继承的本质,实际上就是 "将构造函数的原型对象,指向由另一个构造函数创建的实例". 这里,我们就原型继承的概念,再进行详细的理解.首先 ...
- Java数据库连接泄漏应对办法-基于Weblogic服务器
临时解决连接泄漏方案 当连接泄漏真的发生了,无可避免时,我们采取以下方案,可临时解决连接问题,以争取修改代码的时间. 步骤1:选择待分析的JNDI数据源 步骤2(可选):可配置最大数据连接数量 步骤3 ...
- 作为一个C#程序员, 你应该上手Kotlin
Kotlin最近火了, 在Google IO大会 Kotlin宣布Kotlin将会成为Android官方开发语言之后, Kotlin这样一个JVM上的新*(其实从诞生到现在已经有5年历史的)语言. 终 ...