有过类似C语言编程经验的同学应该都知道“块级作用域(block scope)”:花括号内的每一段代码都具有各自的作用域,而且在声明它们的代码段之外是不可见的。而在JavaScript中是没有块级作用域的,JavaScript取而代之地使用了“函数作用域(function scope)”:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

  光用文字解释平白无味,先来段让你为之一振的代码:

function myTest(num){
var i = 0;
if(num == 222){
var j = 0;
for(var k=0; k<2; k++){
console.log(k);
}
console.log(k);
}
console.log(i);
console.log(j);
console.log(k);
console.log(m);
}
myTest(111);

  请认真阅读代码,仔细思考,认真回答问题。下面给出浏览器中运行的结果,检验下自己的答案吧!

  如果你完全回答正确,并且已经明白所有原因,那么就没必要看下去了;如果你还未明白原因并且有一颗好奇、意欲一探究竟的心,那么就下来就要认真看完本博客了。

  既然不懂,那就再继续认真看解释呗:JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,这就意味着变量在声明之前甚至已经可用了。JavaScript这个特性被非正式地称为声明提前,即JavaScript函数里声明的所有变量(但不涉及赋值)都被提前至函数体的顶部了。这么说上面的例子中代码就等同于

function myTest(num){
var i,j,k;
i = 0;
if(num === 222){
j = 0;
for(k=0; k<2; k++){
console.log(k);
}
console.log(k);
}
console.log(i);
console.log(j);
console.log(k);
console.log(m);
}

  所以即使代码运行时没有进入if条件语句中,但变量i,j,k已经声明了(即使是在for循环中声明的k声明也提前了呢),只是i初始化为0,而j,k没有初始化而已,所以j,k输出是undefined。至于m,因为它根本就没有声明过,所以调用时就报错了。现在明白了吧,下面再来一题自己检测下掌握情况吧:

var str1= "out1";
var str2 = "out2";
function myTest(){
console.log(str1);
console.log(str2);
var str2 = "inner";
console.log(str2);
}
myTest();

  结果是什么呢?下面给出浏览器的回答,检验一下你心中的答案吧!

  给JS学习者一个建议:尽量将变量声明放在函数体顶部,而不是将声明放在使用变量之处,这种做法会使代码清晰地反映了真实的变量的作用域。

补充内容:经过最近的学习,发现这篇博客写的时候自己学的还是不够全面,下面增加一段补充内容:

  ①var 和 function 都是声明语句,它们声明或定义变量或函数。

  ②变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被“提前”至脚本或者函数的顶部,但是初始化操作还在原来赋值语句的位置执行,未初始化的变量的值是undefined。

  ③函数声明语句(注意不是函数定义表达式)中的函数会被显示地“提前”到了脚本或函数的顶部,因此它们在整个脚本和函数内都是可见的,这个时候函数名称和函数体均会提前,也就是说可以在声明一个JavaScript函数之前调用它。关于函数定义表达式,即使用var来定义一个函数,这种形式只有变量声明提前了,变量的初始化仍在原来位置,这时候就不能在初始化之前调用这个函数了。如果不懂这两种函数定义的形式,请继续阅读:下面马上就有例子来区别说明了。

  这里要重点补充的就是:JavaScript中不止在函数中有变量声明提前,在函数外也有变量声明提前。下面还是用代码说话:

  正如预料之中,console.log(aa)输出结果是undefined,而console.log(bb)却因为变量bb在任何位置都没有声明所以就报错。

  再来说说函数声明语句中函数提前的问题,先看一个函数声明语句的例子:

  看到了吧,myConsoleLog 函数就是通过函数声明语句定义的,所以它的函数名和函数体都会提前至顶部,所以在声明语句之前就可以调用它了,下面继续说一个函数定义表达式的例子:

  这次的 myConsoleLog 函数就是通过函数定义表达式定义的,所以myConsoleLog 就是使用var 声明的其他普通变量一样,只有声明提前了,但它初始化还是在第三行那里,所以第一行输出变量myConsoleLog的值就是undefined喽,第二行调用更是会报错了,因为现在myConsoleLog还只是一个值为undefined的普通变量呢,怎么可以作为一个函数来调用啊。

  补充就先到这里吧!!!

下面是在下衷心送给各位看官的五个欢迎(O(∩_∩)O~):欢迎转载、欢迎收藏、欢迎评论、欢迎点赞、欢迎推荐!

JavaScript之函数作用域的更多相关文章

  1. javascript篇-----函数作用域,函数作用域链和声明提前

    在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...

  2. 谈谈javascript的函数作用域

    在一些类似c语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明他们的代码段之外是不可见的,我们称为块级作用域(block scope),而javascript中没有块级作用域.取 ...

  3. javascript中函数作用域和声明提前

    javascript不像java等其他强类型语句,没有块级作用域(括号内的代码都有自己的作用域,变量在声明它们的代码段之外不可见)一说,但有自己的独特地方,即函数作用域. 函数作用域:变量在声明它们的 ...

  4. 深入理解JavaScript的函数作用域

    什么是作用域 ? 作用域:一个变量可以生效的范围. 变量不是在所有地方都可以使用的,而这个变量的使用范围就是我们要说的作用域. 注意:在JavaScript中,划分作用域也是用大括号划分的, 但是在 ...

  5. JavaScript变量的作用域和函数的作用域的区别

    变量作用域和函数作用域都涉及到变量值的变化,本文旨在让大家明白他们之间的区别 变量的作用域: 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接 ...

  6. (转载)javascript函数作用域和提前声明

    http://www.cnblogs.com/ArthurPatten/p/3274080.html 一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们 ...

  7. javascript函数作用域和提前声明

    一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的,但是javascript没有块级作用域.javascript使用函数作用域,即 ...

  8. JavaScript函数作用域和声明提前(3.10.1 page.57)

    <h4>3.函数作用域和声明提前</h4> <p> <!--<script type="text/javascript">-- ...

  9. Javascript之变量作用域

    分析: 无论是强类型语言c#.c++.java等语言,还是弱类型语言如Javascript,所有变量可以抽象为两种类型,即局部变量和全局变量. 全局变量:整个作用域可见. 局部变量:局部可见,退出作用 ...

随机推荐

  1. 银行家算法java实现

    关于银行家算法的理论知识,课本或者百度上有好多资料,我就不再多说了,这里把我最近写的银行家算法的实现带码贴出来. 由于这是我们的一个实验,对系统资源数和进程数都指定了,所以这里也将其指定了,其中系统资 ...

  2. current online redo logfile 丢失的处理方法

    昨天做了rm -rf操作后的恢复演练,并且是在没有不论什么备份的情况下.今天在做破坏性操作前,做了个rman全备,然后在线删除所有数据库文件,包含控制文件,数据文件,在线日志文件,归档文件等.来看看有 ...

  3. nyoj 47 江 河问题 【贪婪】

    经典的贪婪. 两种方案:一个:让我们来最快,第二快,在过去的第一,最快的回.然后最慢,最慢第二,在过去.次最快的回来a[0]+a[1]+a[1]+a[n-1] 二:最快的和最慢的过去,最快的回来,最快 ...

  4. WPF动态加载3D 放大-旋转-平移

    原文:WPF动态加载3D 放大-旋转-平移 WavefrontObjLoader.cs 第二步:ModelVisual3DWithName.cs public class ModelVisual3DW ...

  5. mac在变化mysql-rootpassword-各种解决问题的能力

    官方数据:http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html#resetting-permissions-unix 另值 ...

  6. LayoutInflater使用

    在实际工作中,事先写好的布局文件往往不能满足我们的需求,有时会依据情况在代码中自己定义控件,这就须要用到LayoutInflater.LayoutInflater在Android中是“扩展”的意思,作 ...

  7. 九度OJ 1177 查找 (模拟)

    题目1177:查找 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5659 解决:1667 题目描写叙述: 读入一组字符串(待操作的),再读入一个int n记录记下来有几条命令,总共同拥有 ...

  8. Eclipse热键

    Eclipse编辑功能很强大.掌握Eclipse快捷功能.高开发效率.Eclipse中有例如以下一些和编辑相关的快捷键.     1. [ALT+/]     此快捷键为用户编辑的好帮手.能为用户提供 ...

  9. .NET 4 并行(多核)编程系列之四 Task的休眠

    原文:.NET 4 并行(多核)编程系列之四 Task的休眠 .NET 4 并行(多核)编程系列之四 Task的休眠 前言:之前的几篇文章断断续续的介绍了Task的一些功能:创建,取消.本篇介绍Tas ...

  10. POJ 1659 Frogs&#39; Neighborhood(度序列组成)

    意甲冠军  中国 依据Havel-Hakimi定理构图即可咯  先把顶点按度数从大到小排序  可图的话  度数大的顶点与它后面的度数个顶点相连肯定是满足的  出现了-1就说明不可图了 #include ...