javascript 作用域
作用域:可以理解为在一定范围内对数据进行读、写操作
域:空间、范围、区域...
作用:读、写
浏览器内部,可以暂时把专门用来读取JS的那部分叫做“js解析器”,
“js解析器”工作流程:
“js解析器”在读取代码的时候,会先找一些东西存在仓库里,然后再去逐行解读代码
第一步:找一些东西-->JS的预解析:有变量就是未定义,有函数就是函数的整体
关键字:var 、 function 、参数
变量时:a = 未定义
所有的变量,在正式运行代码前,都提前赋了一个值:未定义
函数时:fn1 = function fn1(){alert(2);}
所有的函数,在正式运行代码前,读取都是整个函数整体
注意:如果函数和变量重名时:只留函数;
函数和函数重名时:只留后者
第二步:逐行解读代码
顺序:从上到下,从左往右-->每读取一行代码就会到“JS的预解析”的那个仓库里看下有没有那个数据
留意表达式: = + - * / ++ -- 参数 ! 等所有能改变值的表达式,遇到表达式的时候会去修改预解析仓库里的值
留意函数调用:如果遇到函数调用,就在函数体内开了一个新的作用域,以当前函数为单位来进行预解析及逐行解读代码,如果在预解析的过程中,发现函数体内既没有var又没有function的时候,就会向它上一级元素(父元素)里去找想要的东西。(作用域链)
实例1:
<script type="text/javascript">
alert(a); // function a(){alert(4);} ----> 结果为仓库里的值
var a=1; // 此行代码为表达式 --->把仓库的值a由function a(){alert(4);} 改为 1
alert(a); // 1
function a(){
alert(2);
} //此处为声明函数 ,没有被调用,忽略
alert(a); // 1
var a=3; // 此行代码为表达式 --->把仓库的值a由1改为3
alert(a); // 3
function a(){
alert(4);
} //此处为声明函数,没有被调用,忽略
alert(a); // 3
alert(typeof a); // number
a(); //报错 :a is not a function --->此时仓库只有值a=3,并未有函数,所以此调用不合法,会报错
</script>
分析:
“js解析器”在读取这段代码的时候,会先在代码里找到一些关键字(var、function),把他存到仓库里.
上例中,仓库出现过的值依次为:
1) a = undefined
2) a = function a(){
alert(2);
}
3) a = undefined
4) a = function a(){
alert(4);
}
但是,解析器在解析代码时,会遵循以下原则:
如果函数和变量重名:只留函数;函数和函数重名:只留后者。
所以,最终仓库里的值为: a = function a(){alert(4);}
完成以上步骤后,解析器开始逐行解读代码,结果见例子注释部分。
实例2:
<script type="text/javascript">
var a = 1; // 仓库里的a由undefined变成1
function fn1(a){
alert(a); // undefined
a = 2; // 仓库里的a由undefined变成了2
} //函数声明,忽略
fn1(); // 此处发生函数调用,对fn1开始预解析及逐行解读代码
alert(a); // 1 这里的a是全局变量的,不是fn1里面的a,所以值为1
</script>
分析:
预解析:
a = undefined
fn1 = function fn1(a){
alert(a);
a = 2;
}
逐行解读代码:执行到fn1()的时候, 发生了函数调用,所以对fn1开始预解析及逐行解读代码,如下:
fn1函数的预解析:
fn1有一个参数a,所以此时a = undefined
逐行解读代码:
function fn1(a){
alert(a); // undefined
a = 2; // 仓库里的a由undefined变成了2
}
实际应用:
1)局部变量可以改变全局变量的值。
2)
function fn1(){
var a ="lily";
}
alert(a); // 报错,外部不可直接访问函数内的变量
想获取函数内部的值:
1)用全局变量去获取函数内的值(作用域链)
<script type="text/javascript">
var str= "";
function fn1(){
var a = "lily";
str = a;
}
fn1();
alert(str); //lily
</script>
2) 通过函数调用,(让fn3能弹出出fn2的内容)
<script type="text/javascript">
function fn2(){
var a="lily"; //此时仓库里由a=undefined变成a='lily'
fn3(a); //逐行解读代码的时候找不到关于fn3的,所以会去下边的fn3函数里找
}
fn2(); //发生函数调用,然后对fn2预解析并逐行解读代码
function fn3(a){
alert(a); //lily
}
</script>
解析:
首先通过函数调用fn2(),来预解析fn2()函数里的代码,此时a=undefined;
解析完毕,开始去逐行解读fn2这个函数.如下:
var a="lily"; 此时a由undefined变成lily,
读到fn3(a)这句代码的时候,在fn2这个函数里找不到相关的东西,所以会去函数外面找,找到了fn3这个函数,通过传参在fn3函数里得到fn2函数a的值。
(根据妙味的课程整理)
javascript 作用域的更多相关文章
- JavaScript作用域
JavaScript作用域 JavaScript作用域一直是前端开发的难题,现在只要用五句话就可解决. 一.“JavaScript中无块级作用域” 在Java或C#中存在块级作用域,即:大括号也是一个 ...
- 关于Javascript作用域及作用域链的总结
本文是根据以下文章以及<Javascript高级程序设计(第三版)>第四章相关内容总结的. 1.Javascript作用域原理,地址:http://www.laruence.com/200 ...
- JavaScript作用域链
之前写过一篇JavaScript 闭包究竟是什么的文章理解闭包,觉得写得很清晰,可以简单理解闭包产生原因,但看评论都在说了解了作用域链和活动对象才能真正理解闭包,起初不以为然,后来在跟公司同事交流的时 ...
- [译] 你该知道的javascript作用域 (javascript scope)(转)
javascript有一些对于初学者甚至是有经验的开发者都难以理解的概念. 这个部分是针对那些听到 : 作用域, 闭包, this, 命名空间, 函数作用域, 函数作用域, 全局作用域, 变量作用域( ...
- Python自动化 【第十六篇】:JavaScript作用域和Dom收尾
本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走 ...
- 深入理解javascript作用域系列第一篇——内部原理
× 目录 [1]编译 [2]执行 [3]查询[4]嵌套[5]异常[6]原理 前面的话 javascript拥有一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量,这套规则被称为作用域.作用域 ...
- 深入理解javascript作用域系列第二篇——词法作用域和动态作用域
× 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极 ...
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
- 深入理解javascript作用域系列第三篇——声明提升(hoisting)
× 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javasc ...
- JavaScript作用域原理(三)——作用域根据函数划分
一.一个for实例 <p id="scope3" style="color:red"></p> var pscope3 = docume ...
随机推荐
- Apache Spark技术实战之1 -- KafkaWordCount
欢迎转载,转载请注明出处,徽沪一郎. 概要 Spark应用开发实践性非常强,很多时候可能都会将时间花费在环境的搭建和运行上,如果有一个比较好的指导将会大大的缩短应用开发流程.Spark Streami ...
- php实现多线程
php实现多线程 感谢 3lian8 的投递 时间:2014-01-21 来源:三联教程 有没有办法在php中实现多线程呢?假设你正在写一个基于多台服务器的php应用,理想的情况时同时向多台服务器发送 ...
- Cloudera Hadoop什么是CDH及CDH版本介绍
本文引用自:Cloudera Hadoop什么是CDH及CDH版本介绍http://www.aboutyun.com/thread-6788-1-1.html(出处: about云开发) 云技术新兴的 ...
- python标准库介绍
操作系统接口 os模块提供了不少与操作系统相关联的函数. >>> import os >>> os.getcwd() # 返回当前的工作目录 'C:\\Python ...
- hadoop 2.4 伪分布式模式
1.core-site.xml 在<configuration></configuration>中插入 <property> <name>fs.defa ...
- 【Java 基础篇】【第四课】初识类
看看Java中如何定义一个类,然后用来调用的,这个比较简单,直接看代码吧. 我发现的类和C++不一样的地方: 1.Java中类定义大括号后没有分号: 2.好像没有 public.private等关键字 ...
- php-- memcache 与 memcached支架的区别与共同点 个人整理
首先声明:memcache 与 memcached 之间没有关系 1.概念相似 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载. m ...
- iOS Provisioning Profile(Certificate)与Code Signing详解
引言 关于开发证书配置(Certificates & Identifiers & Provisioning Profiles),相信做 iOS 开发的同学没少被折腾.对于一个 iOS ...
- LoadingView 自定义加载图片
#import <UIKit/UIKit.h> @interface LoadingView : UIView @property (nonatomic,strong) NSMutable ...
- 实战案例:DIV嵌套
缘于页面结构语义化的考虑,我们应该慎用div和span这两个通用元素,只有当划分页面结构模块时才使用div元素,因为模块本身是没有任何语义的,他仅代表一块独立的结构.如果想对段落内部分内联元素或文本应 ...