关于JavaScript的作用域,最近听到一个名词:“词法作用域”;以前没有听说过(读书少),记录一下对此的理解,加深印象。

词法作用域:在JavaScript中,一个函数的作用域,在这个函数定义好的时候就决定好了;因此判断该函数的上一级作用域,不是看函数在哪里调用,而是看函数在哪里编写;请勿和this进行混淆了

第1个例子:

 function fn(callback){
var age=18;
callback()
} fn(function(){
console.log(age) // 此处会输出什么结果?
})

分析:在第3行代码调用匿名函数时,会在匿名函数的作用域范围内查找age变量,此时的作用域是找不到age变量的;所以会查找匿名函数的上一级,重点是该匿名函数的上一级作用域是什么?好,下面在看一个例子。

第2个例子:

 function fn(cb){
var age=18;
cb()
} function callback(){
console.log(age) // 此处会输出什么结果?
} fn(callback);

分析:第二个例子相对于第一个列子来说,只是把匿名函数改成了callback函数而已。由第二个例子可以很明确的看出,callback函数的上一级作用域其实是全局作用域,即是window;在callback函数的作用域内,找不到age变量;因此需要网上一级查找,在全局作用域window中也找不到age变量,所以,以上两个例子的输出结果都是报以下的错误:

总结:由上面的两个例子可以看出,在JavaScript中,判断一个函数的上一级作用域是什么?需要看这个函数时在哪个作用域中声明的,而不是在哪个作用域调用的;这就是JavaScript的词法作用域。

 第3个例子:

 var x = "globol value";
function getValue(){
console.log(x); // 此处会输出什么?
var x = "local value";
console.log(x); // 此处会出输出什么?
}
getValue();

分析:按照前面两个例子的词法作用域进行分析,getValue函数是在全局作用域window中编写的,所以是可以访问到window作用域的x变量的,按理来说,输出的结果应该会是:“globol value”和“local value”的;但是,在ES6之前,使用var声明的变量,会存在变量提升即将变量声明提升到它所在作用域的最开始的部分,类似于函数声明提升( function declaration hoisting);因此第3个例子可以改写为如下代码:

 var x = "globol value";
function getValue(){
var x; // 声明变量,不进行赋值,默认值为undefined
console.log(x);
x = "local value";
console.log(x);
}
getValue();

所以,第3个例子输出的结果是:undefined和“local value”;如果想要输出“globol value”和“local value”,那么可以改为如下代码:

 var x = "globol value";
function getValue(){
console.log(window.x);
var x = "local value";
console.log(x);
}
getValue();

PS:在ES6中,如果使用let和const关键字来声明变量,是不会存在变量提升的效果的。有兴趣的朋友可以执行一下以下的代码,看看是什么效果,要理解下面这个例子的结果,可以去看看阮一峰老师的关于let的暂时性死区的阐述:http://es6.ruanyifeng.com/#docs/let

 var x = "globol value";
function getValue(){
console.log(x);
let x = "local value";
console.log(x);
}
getValue();

关于JavaScript的词法作用域及变量提升的个人理解的更多相关文章

  1. javascript中的作用域和变量提升

    js的运行主要分两个阶段:js的预解析和运行,预解析阶段所有的变量声明和函数定义都会提前,但是变量的赋值不会提前.

  2. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  3. javascript中的变量作用域以及变量提升详细介绍

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...

  4. Javascript作用域和变量提升

    下面的程序是什么结果? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 结果是10: 那么 ...

  5. JS 函数作用域及变量提升那些事!

    虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...

  6. JS _函数作用域及变量提升

    虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...

  7. JS作用域、变量提升和闭包

    作用域 作用域可以理解为JS引擎执行代码的时候,查找变量的规则. 从确定变量访问范围的阶段的角度,可以分为2类,词法作用域和动态作用域.js是词法作用域. 从变量查找的范围的角度,可以分为3类,全局作 ...

  8. JS高级. 05 词法作用域、变量名提升、作用域链、闭包

    作用域 域,表示的是一个范围,作用域,就是作用范围. 作用域说明的是一个变量可以在什么地方被使用,什么地方不能被使用. 块级作用域 JavaScript中没有块级作用域 { var num = 123 ...

  9. JavaScript基础03——函数的作用域及变量提升

    1.作用域 作用域,变量在函数内部作用的范围/区域.有函数的地方就有作用域.   2.局部作用域和全局作用域 function fn(){ var a = 1; } console.log(a); / ...

随机推荐

  1. 5、docker容器数据卷: -v添加共享传递容器数据卷

    1.是什么 1.docker理念 先来看看Docker的理念:*  将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的*  容器之间希望有可能共享数据 2.保 ...

  2. Finding Lane Lines on the Road

    Finding Lane Lines on the Road The goals / steps of this project are the following: Make a pipeline ...

  3. javascript内置对象一: Array数组

    在JavaScript中的任何事物,字符串,数组,函数等等都是对象. 理解:浏览器自己封装好的对象,可以直接使用. push   /pʊʃ/  增加 在末尾增加              unshif ...

  4. 泛目录程序(莲花泛目录程序/黑帽SEO/寄生虫/莲花泛目录解析/泛目录软件)

    莲花泛目录程序强大之处: 1.内容分类详细2.自动推送URL链接3.内置超强原创内容功能系统,页面深受百度搜索引擎喜爱.4.蜘蛛触发繁殖:蜘蛛触发程序任何页面,程序自动生成独立页面并引导繁殖.5.操作 ...

  5. js切换全屏

    直接撸代码 //<a id="fullscreen">切换按钮</a> $('#fullscreen').bind('click',function () ...

  6. iOS学习之Autolayout

    转载自:http://vit0.com/blog/2013/12/07/iosxue-xi-zhi-autolayout/ 学习资料 文章 Beginning Auto Layout Tutorial ...

  7. 云闪付个人免签支付用xposed解决强制升级

    云闪付的xposed程序之前用的是6.18的版本,前段时间突然不能用了,提示要升级到最新的7.0版本.之前这个云闪付的个人免签支付程序一直跑的挺好,云闪付也是所有免签支付里面最能跑量的,不甘就这么放弃 ...

  8. 解决:安装jenkins时web界面出现jenkins实例似乎已离线问题

    https://blog.51cto.com/8593714/2318144?tdsourcetag=s_pctim_aiomsg Windows下环境也可以解决:

  9. 【JDBC】使用Spring提供的JDBCTemplate通过PrepareStatement向MySql数据库插入千万条数据,耗时32m47s,速度提升有限

    数据库环境还和原来一样,只是从Statement换成了PrepareStatement,都说PrepareStatement因为预编译比Statement快,但是实际运行真快不了多少. 代码如下: p ...

  10. 【Java】给整数加上千分位分隔符

    package com.testEmp; import java.text.DecimalFormat; public class NumberFormat { public static void ...