变量作用域

在JavaScript中,用var申明的变量实际上是有作用域的。

如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量。

如果两个不同的函数各自申明了同一变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响。

由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:

    function foo() {
var x = 1;
function bar() {
var y = x + 1 ;//bar可以访问foo的变量x
}
var z = y + 1;//ReferenceError!foo不可以访问bar的变量y!
}

如果内部函数和外部函数的变量名重名怎么办?

    function foo() {
var x = 1;
function bar() {
var x = 'A';
alert('x in bar() =' + x);//'A'
}
alert('x in foo() =' + x );//
bar();
}

JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。

变量提升

JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

    function foo() {
var x = "Hello," + y ;
alert(x);
var y = "Bob";
} foo();//Hello,undefined

语句 var x = "Hello," + y ;并不会报错,原因是变量y在稍后申明了。但是alert显示的是Hello,undefined,说明变量y的值是undefined,这正是因为JavaScript引擎自动提升了变量y的声明,但是不会提升变量y的赋值语句。

对于上述的foo()函数,JavaScript引擎看到的代码相当于:

          function foo() {
var y;//提升变量y的申明
var x = 'Hello,' + y ;
alert(x);
y='Bob';
}

tips:所以在JavaScript函数内部要首先申明所有变量。最常见的做法是用一个var申明函数内部用到的所有变量:

    function foo() {
var
x=1,//x初始化为1
y=x+1,//y初始化为2
z,i;//z和i为undefined
//其他语句
for(i = 0; i<100; i++){
...
}
}

全局作用域

不在任何函数内定义的变量就具有全局作用域。JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性:

     var course = 'Learn JavaScript';
alert(course);//'Learn JavaScript'
alert(window.course);//'Learn JavaScript'

因此,直接访问全局变量course和访问window.course是完全一样的。

由于函数定义有两种方式,以变量方式var foo = function () {}定义的函数实际上也是一个全局变量。因此,顶层函数的定义也被视为一个全局变量

名字空间

全局变量会绑定到window上,不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。

减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。

  //唯一的全局变量MYAPP:
var MYAPP = {};
//其他变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
//其他函数
MYAPP.foo = function () {
return 'foo';
};

把自己的代码全部放入唯一的命名空间MYAPP中,会大大减少全局变量冲突的可能。

局部作用域

由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中无法定义具有局部作用域的变量:

  'use strict':
function foo() {
for( var i = 0 ; i < 100; i++){
//
}
i +=100;//仍然可以引用变量i
}

为了解决块级作用域,ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量:

  'use strict':
function foo() {
var sum = 0 ;
for (let i = 0 ; i < 100 ; i++){
sum +=i;
}
i += 1;//SyntaxError
}

常量:

由于var和let申明的是变量,在ES6之前是不行的,我们通常用全部大写的变量来表示“这是一个常量,不要修改它的值”:

var PI = 3.14;

ES6标准引入了新的关键字const来定义常量,const与let都具有块级作用域:

  'use strict':
const PI = 3.14;
PI = 3;//某些浏览器不报错,但是无效果!
PI;//3.14

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

  1. [转]深入理解JavaScript的变量作用域

    1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定 ...

  2. 深入理解JavaScript的变量作用域(转载Rain Man之作)

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  3. 深入理解JavaScript的变量作用域

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  4. 函数变量作用域(python)

    收集参数:该参数个数不确定 >>> def test(*params): print('参数的长度是:', len(params)); print('第二个参数是:', params ...

  5. Javascript之变量作用域

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

  6. javascript的变量作用域--对比js、php和c的for循环

    为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...

  7. [译]JavaScript:函数的作用域链

    原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...

  8. javascript 函数和作用域(函数,this)(六)

    重点. 一.函数 1.函数介绍 函数是一块JavaScript代码,被定义一次,但可执行和调用多次.JS中的函数也是对象,所以JS函数可以像其他对象那样操作和传递,所以我们也常叫JS中的函数为函数对象 ...

  9. javascript 函数和作用域(闭包、作用域)(七)

    一.闭包 JavaScript中允许嵌套函数,允许函数用作数据(可以把函数赋值给变量,存储在对象属性中,存储在数组元素中),并且使用词法作用域,这些因素相互交互,创造了惊人的,强大的闭包效果.[upd ...

随机推荐

  1. 九度oj题目1153:括号匹配问题

    题目1153:括号匹配问题 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4866 解决:2112 题目描述: 在某个字符串(长度不超过100)中有左括号.右括号和大小写字母:规定(与常见 ...

  2. nyoj 349&Poj 1094 Sorting It All Out——————【拓扑应用】

    Sorting It All Out 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 An ascending sorted sequence of distinct ...

  3. 【Shell】运行shell出现-ash: ./test.sh: not found

    1.这是一个读取文件的脚本 #!/bin/bash for line in `cat pidtestconf` do echo $line done 因为命名的时候这边使用的是 test.sh 这边将 ...

  4. 01.使用File类读写文件

    使用File类去读数据: 方法一:使用ReadAllBytes(); 方法 namespace _01.使用File类读写数据01 { class Program { static void Main ...

  5. pwn 题GDB调试技巧和exp模板

    GDB分析ELF文件常用的调试技巧 gdb常用命令 首先是gbd+文件名 静态调试 ,gdb attach +文件名 动态调试 为了方便查看堆栈和寄存器 最好是安装peda插件 安装 可以通过pip直 ...

  6. Jms学习篇二:ActiveMQ

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线 安装 1>下载:到http://activemq.apache.org/download.html 下载最新版本, 解压a ...

  7. 【Android】6.0 添加Menu菜单组件、Intent启动活动、显式Intent、隐式Intent

    1.0 在helloworld项目基础上创建活动SecondActivity: 2.0 其中main.xml: <?xml version="1.0" encoding=&q ...

  8. 对于在gti操作遇见detached Head时

    1.什么是detached HEAD 在git中,这是一个处于”游离“状态的标签 2.使用git branch <new_branch_name> <HEAD_code> 为这 ...

  9. linux c 遍历目录及文件

    #include <dirent.h>void recovery_backend() { DIR * pdir ; struct dirent * pdirent; struct stat ...

  10. WebLogic配置与部署

    一.创建域: 第一步,选择“开始菜单”-> “Oracle WebLogic”-> “WebLogic Server 10gR3” -> “Tools”-> “Configur ...