上一篇文章中简单介绍了一下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。

四句话总结JavaScript作用域的更多相关文章

  1. 四句话表明JSON格式定义

    (1):并列的数据之间使用逗号(",")分割: (2):键值对的映射用冒号(":")表示: (3):并列数据的集合(数组)用方括号("[]" ...

  2. 五句话搞定JavaScript作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  3. 【】五句话搞定JavaScript作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  4. 五句话搞定JavaScript作用域(ES5)

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  5. 五句话搞定JavaScript作用域【转】

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  6. 160630、五句话搞定JavaScript作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕.   一.“JavaScript中无块级作用域” 在Java或C# ...

  7. 【Python之路】特别篇--五句话搞定JavaScript作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  8. JS作用域就这么几句话

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  9. 5句话搞定ES5作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

随机推荐

  1. 使用dispatch_once:创建单列

    无论是爱还是恨,你都需要单例.实际上每个iOS或Mac OS应用都至少会有UIApplication或NSApplication. 什么是单例呢?Wikipedia是如此定义的: 在软件工程中,单例是 ...

  2. JavaScript实现竖直文本滚动

    一.HTML代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  3. [Javascript] Drawing Paths - Curves and Arcs

    window.onload = function() { var canvas = document.getElementById("canvas"), context = can ...

  4. java24 手写服务器最终版本

    手写服务器最终版本; <?xml version="1.0" encoding="UTF-8"?> <web-app> <serv ...

  5. 标准I/O的替代软件

    标准I/O并不完善. 标准I/O库的一个不足之处是效率不高,这与它需要复制的数据量有关.当使用每次一行函数fgets和fputs时,通常需要复制两次数据:一次是在内核和标准I/O缓冲之间(当调用rea ...

  6. Android(java)学习笔记159:Dalivk虚拟机的初始化过程

    1.初始化下面系统函数(调用dvmStartup函数初始化所有相关的函数) 开始学习虚拟机的初始化过程,先从dvmStartup函数开始,这个函数实现所有开始虚拟机的准备工作: dvmAllocTra ...

  7. python--class test

    # !usr/bin/env  python3#-*- coding:utf-8 -*- 'a test class'class Student(object):    def __init__(se ...

  8. Asp.Net MVC--Controller激活2

    在使用MVC项目中,如果激活控制器,则就会向前台返回action执行的结果. 很多时候,根据需求,手动激活控制器来向客户端返回结果. 一.激活实例代码1 这是在Global文件中使用 var rout ...

  9. mysql insert语句错误问题解决

    好久没有复习数据库了,竟然忘记了mysql中的关键字(保留字),导致今天一晚上都在查找sql语句错误,特此记录此错误,教训啊. 我在mysql数据库中有一个名为order 的表,啊啊啊啊啊,为啥我给他 ...

  10. Opencv读取视频一闪而过情况分析

    在参加一个软件比赛需要用opencv对视频的处理,也碰到了一些问题. 最常见的就是视频一闪而过了,在网上查了好久都没解决, 最后重装在配置环境变量时发现的. 现在我来终结一下估计是比较全的了. 先说明 ...