上一篇文章中简单介绍了一下JS作用域,本篇将作进一步探究和总结。

前言:JavaScript的作用域一直以来都是前端开发中比较难以理解的知识点,JavaScript6中新引入了 let 关键字,用于指定变量属于块级作用域,本次先忽略这个点。

第一句话:JavaScript以函数作为作用域(忽略let)

  很多语言如c#,java都是以代码块作为作用域即大括号也是一个作用域,JavaScript却是以函数作为作用域,如果你对python比较了解,理解起来应该很easy。

在c#中下面的代码将直接报错:

 public void Func(){
if(==){
string name = 'Java'; }
console.writeline(name); }
Func()
// 报错

在JavaScript语言中无块级作用域:

 function Main(){
if(1==1){
var name = 'seven';
}
console.log(name);
}
// 输出: seven

我们先来回忆一下python的作用域(如果不会python可以跳过,不影响后面阅读):

 # 情况一:
def func():
if 1 == 1:
name = 'alex'
print(name)
func()
# 成功 # 情况二:
def func():
if 1 == 1:
name = 'alex'
print(name) func()
print(name)
# // 报错

再来看看JavaScript采用函数作用域:

 function Main(){
var innerValue = 'seven';
} Main(); console.log(innerValue); // 报错:Uncaught ReferenceError: innerValue is not defined

  在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。console.log(innerValue)访问函数Main()中的变量肯定是不行的。

第二句话:JavaScript函数的作用域在函数未被调用之前,已经创建

  在JavaScript中如果不创建(声明)变量,直接去使用,则报错:

 console.log(x);
VM199:1 Uncaught ReferenceError: x is not defined(…)

  JavaScript中如果创建值而不赋值,则该值为 undefined,如:

 var num;
console.log(num); //undefined

了解了这个看看下面这个函数:

 function func(){
if(1==1){
var name = 'alex';
}
console.log(name);
}

  在浏览器中直接输入这个函数会得到undefined,而不是报错,就说明变量name在函数调用之前就创建(声明)了,但没有被赋值。

第三句话:函数的作用域存在作用域链,并且也是在被调用之前创建

  1 <script>
2 x = "alex";
3 function func() {
4 var x = "eric";
5 function inner() {
6 var x = "tony";
7 console.log(x);
8 }
9 inner();
10 }
11 func();
12 </script>

输出结果是tony。

如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:

当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。

练习题1:

 x = "alex";
function func() {
var x = "eric";
function inner() {
console.log(x);
}
return inner;
}
var res = func();
res();

结果:eric

上述代码,在函数被调用之前作用域链已经存在:

  • 全局作用域 -> func函数作用域 -> inner函数作用域

当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。

练习题2:

 x = "alex";
function func() {
var x = "eric";
function inner() {
console.log(x);
}
var x = 'tony';
return inner;
}
var res = func();
res();

结果:tony

第四句话: 函数内局部变量 声明提前

 function func(){
console.log(xo);
var xo = 'alex';
} func();
// undefined

上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。

最新文章

  1. Socket编程实践(1) 基本概念
  2. Python for Infomatics 第13章 网页服务四(译)
  3. java mybatis 框架下多种类型的参数传入到xml问题
  4. ★★★.NET 在meta标签中使用表达式设置页面的关键字
  5. radio select的 option使用
  6. poj 3592 Instantaneous Transference
  7. css float父元素高度塌陷
  8. 安装setuptools和pip
  9. 《Linux 设备驱动程序》读后感。 并发,竞态,死锁。
  10. NSLocalizedString不起作用
  11. Pivot Table系列之切片器 (Slicer)
  12. poj 1741
  13. 三星I939D手机刷机记录
  14. [Python学习笔记] turtle库的基本使用
  15. springcloud注解@EnableDiscoveryClient与@EnableEurekaC
  16. MongoDB文档的增删改操作
  17. phpStudy安装
  18. 关于office2016桌面新建不显示execl问题
  19. OMAP4之DSP核(Tesla)软件开发学习(二)Linux内核驱动支持OMAP4 DSP核
  20. bzoj 1261 区间DP

热门文章

  1. sublime text快捷键
  2. leetcode一些常用函数
  3. C库函数使用与总结之时间函数
  4. 1122从业务优化MYSQL
  5. Node.js入门笔记(5):案例两则
  6. SqlServer性能优化(一)
  7. C++ 数组长度 以及 数组名作为参数传递给函数 以及 为什么不在子函数中求数组长度
  8. 一、HTML和CSS基础--网页布局--实践--固定层效果
  9. 基于Spark ALS构建商品推荐引擎
  10. QTP数据驱动之读取Excel数据
  11. .net批量删除和添加
  12. 概率图模型(PGM)学习笔记(三)模式判断与概率图流
  13. delphi 中COPY()函数的意思
  14. 【找不到与请求 URI匹配的 HTTP 资源】(转)
  15. 理解JDK1.5的自动装箱拆箱
  16. 使用Python从Workflowy同步大纲到印象笔记
  17. Android高版本联网失败报错:Cleartext HTTP traffic to xxx not permitted解决方法
  18. 部署WebService
  19. [hdu6148][Valley Numer]
  20. how to check CAN frame