变量作用域

在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. vim代码折叠命令

    1. 折叠方式 可用选项 'foldmethod' 来设定折叠方式:set fdm=*****. 有 6 种方法来选定折叠:           manual           手工定义折叠 ind ...

  2. git本地创建新分支并推送到远程仓库

    1,在当前项目目录,从已有的分支创建新的分支(如从master分支),创建一个dev分支 git checkout -b dev 2,创建完可以查看一下,分支已经切换到dev git branch * ...

  3. 项目视图 Project Browser

    项目视图 在这个视图,你可以访问.管理你当前项目资源. 项目视图左侧面板显示项目的文件夹结构的分层列表,当从列表中单击一个文件夹,其内容会显示在面板的右边.你可以点击小三角展开或折叠文件夹,显示他包含 ...

  4. 打包.NET Core的程序到一个单独的可执行文件

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:打包.NET Core的程序到一个单独的可执行文件.

  5. mvc中RedirectToAction()如何传参?

    今天在做一个功能的时,使用RedirectToAction()需要从这里传几个参数,从网上查了一下,这样解决.真好. Return RedirectToAction("Index" ...

  6. java线程安全问题原理性分析

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题:如果在整个访问过程中,无一对象被其他线程修改,就是线程安全 ...

  7. phpmyadmin-错误:配置文件权限错误,不应任何用户都能修改!这里有答案

    今天在linux下使用phpMyadmin的时候突然出现这个红色警告.差点把我吓晕在电脑前.不过冷静想一下这个报错,肯定就是linux权限那几个 ‘7’ 惹的祸. 于是 通过命令  ‘ll’ (这是英 ...

  8. 如何angular过滤器进行排序???

    首先定义一个json文件: 然后写HTML文件: <div id="box"> <!--第一个下拉框--> <select ng-model=&quo ...

  9. Elasticsearch 5.1.1 head插件安装指南

    一.下载安装包 下载Elasticsearch 5.1.1 下载地址:https://www.elastic.co/downloads/elasticsearch zip和tar格式是各种系统都通用的 ...

  10. Linux中基于apache httpd的svn服务器搭建与配置

    mod_dav_svn是apache连接svn的模块 yum install subversion mod_dav_svn httpd 配置文件简单说明, SVNParentPath 说明可以在指定的 ...