作用域

作用域是指程序源代码中定义变量的区域。

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。

静态作用域与动态作用域

因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。

而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。

让我们认真看个例子就能明白之间的区别:

var value = 1;

function foo() {
console.log(value);
} function bar() {
var value = 2;
foo();
} bar(); // 结果是 ???

假设JavaScript采用静态作用域,让我们分析下执行过程:

执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。

假设JavaScript采用动态作用域,让我们分析下执行过程:

执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。

前面我们已经说了,JavaScript采用的是静态作用域,所以这个例子的结果是 1。

动态作用域

也许你会好奇什么语言是动态作用域?

bash 就是动态作用域,不信的话,把下面的脚本存成例如 scope.bash,然后进入相应的目录,用命令行执行 bash ./scope.bash,看看打印的值是多少。

value=1
function foo () {
echo $value;
}
function bar () {
local value=2;
foo;
}
bar

这个文件也可以在 Github 博客仓库中找到。

思考题

最后,让我们看一个《JavaScript权威指南》中的例子:

var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();

猜猜两段代码各自的执行结果是多少?

这里直接告诉大家结果,两段代码都会打印:local scope

原因也很简单,因为JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。

而引用《JavaScript权威指南》的回答就是:

JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。

但是在这里真正想让大家思考的是:

虽然两段代码执行的结果一样,但是两段代码究竟有哪些不同呢?

如果要回答这个问题,就要牵涉到很多的内容,词法作用域只是其中的一小部分,让我们期待下一篇文章————《JavaScript深入之执行上下文栈》。

原文:https://www.cnblogs.com/guaidianqiao/p/7762070.html

【作用域】词法作用域(静态作用域,如:js)、动态作用域(如:.bash脚本)的更多相关文章

  1. 深入学习js之——词法作用域和动态作用域

    开篇 当我们在开始学习任何一门语言的时候,都会接触到变量的概念,变量的出现其实是为了解决一个问题,为的是存储某些值,进而,存储某些值的目的是为了在之后对这个值进行访问或者修改,正是这种存储和访问变量的 ...

  2. 词法作用域 vs 动态作用域

    词法作用域 vs 动态作用域 链接:https://www.jianshu.com/p/cdebb5965000 scheme是一门采用词法作用域(lexical scoping)的lisp方言,这个 ...

  3. 动态作用域与this +apply和call +bind

    词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则. (函数作用域和块作用域) JavaScript 中的作用域就是词法作用域,也就是静态作用域,由定义代码决定 动态作用域似乎暗示有很好的 ...

  4. 区分词法作用域(js)与动态作用域(精!)

    在js学习中,词法作用域是必须要掌握的! 在这里,我将总结一下<你不知道的JS>一书中词法作用域的重点并分享给大家! 首先带来一段代码示例: function foo(){ console ...

  5. js之词法作用域与动态作用域

    事实上JavaScript并不具有动态作用域,它只有词法作用域,简单明了,但是this机制某种程度上很像动态作用域 词法作用域:是一套引擎如何寻找变量以及会在何处找到变量的规则,它是定义在词法阶段的作 ...

  6. JavaScript 词法、静态、动态作用域初级理解

    开始之前 由于本人也是JavaScript初学者,记录学习经过,怕以后会忘记. 对于JavaScript 初学者来说,最难的不是代码部分,而是对很多书籍中的术语的理解,大多时候想要理解一段JavaSc ...

  7. 你不知道的JS之作用域和闭包(二)词法作用域

    原文:你不知道的js系列 词法作用域(Lexical Scope) Lex time 一个标准的编译器的第一个阶段就是分词(token化) 词法作用域就是在词法分析时定义的作用域.换句话说,词法作用域 ...

  8. JavaScript深入之词法作用域和动态作用域

    作用域 作用域是指程序源代码中定义变量的区域. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限. JavaScript 采用词法作用域,也就是静态作用域. 静态作用域与动态作用域 因 ...

  9. Javascript中的词法作用域、动态作用域、函数作用域和块作用域(四)

    一.js中的词法作用域和动态作用域      词法作用域也就是在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了.       js中其实只有词法作用域,并没有动态作用域,this的执 ...

随机推荐

  1. c语言新知

    C语言学得有点懈怠,昨个遇一个高手. 教了我两天,真细腻. 第一天,让我写一个程序删除字符串多余空格. 我俩代码对比   结果很显然了.

  2. 学习linux开发需要的基础

    1.常见的通信协议I2C和SPI,熟悉. 还有时钟. 中断等概念也都了解了. 所以你现在应该先学一下Linux常用的一些命令,网上搜一下,有很多总结的文章,大概看一下用法,想深入学习的话,可以看鸟哥的 ...

  3. Django常用知识整理

    Django 的认识,面试题 1. 对Django的认识? #1.Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构.以及全 ...

  4. nginx rewrite重写规则简明笔记

    nginx rewrite重写规则简明笔记 比方说http://newmiracle.cn/?p=888我要改成能这个访问http://newmiracle.cn/p888/ 首先用正则获取888 ^ ...

  5. 奥展项目笔记06--js弹出框、对话框、提示框、弹窗总结

    JS的三种最常见的对话框: //====================== JS最常用三种弹出对话框 ======================== //弹出对话框并输出一段提示信息 functi ...

  6. WPF 通过Win32SDK修改窗口样式

    使用函数为 SetWindowLong GetWindowLong 注册函数 [DllImport("user32.dll", EntryPoint = "GetWind ...

  7. Python 线程池(小节)

    Python 线程池(小节) from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor import os,time, ...

  8. spring boot入门,看这篇文章就够了

    一.SpringBoot入门 1.基本介绍 简化Spring应用开发的一个框架.整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 优点: 快速创建独立运行的Spring项目以及与主 ...

  9. scrapy学习笔记(一)

    环境:Windows 7  x64   Python3.7.1  pycharm 一.安装scrapy 1.1linux系统使用:pip install scrapy 1.2Windows系统: pi ...

  10. 动手动脑,第六次Tutorial——数组和随机数数组输出及求和

    作业课后作业1 阅读QiPan.java示例程序了解如何利用二维数组和循环语句绘制五子棋盘. 首先,定义string类型的二维数组,它和类的数组不一样,类的数组分配了空间后不能直接for循环赋值,st ...