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


Posted in Javascript onOctober 24, 2013

变量作用域
“一个变量的作用域表示这个变量存在的上下文。它指定了你可以访问哪些变量以及你是否有权限访问某个变量。”

变量作用域分为局部作用域和全局作用域。

局部变量(处于函数级别的作用域)
不像其他对面对象的编程语言(比方说C++,Java等等),javascript没有块级作用域(被花括号包围的);当是,javascript有拥有函数级别的作用域,也就是说,在一个函数内定义的变量只能在函数内部访问或者这个函数内部的函数访问(闭包除外,这个我们过几天再写个专题)。

函数级别作用域的一个例子:

var name = "Richard";function showName () {
    var name = "Jack"; // local variable; only accessible in this showName function
    console.log (name); // Jack
}
console.log (name); // Richard: the global variable

没有块级作用域:

var name = "Richard";
// the blocks in this if statement do not create a local context for the name variable
if (name) {
    name = "Jack"; // this name is the global name variable and it is being changed to "Jack" here
    console.log (name); // Jack: still the global variable
}// Here, the name variable is the same global name variable, but it was changed in the if statement
console.log (name); // Jack

//    不要忘记使用var关键字
//    如果声明一个变量的时候没有使用var关键字,那么这个变量将是一个全局变量!
// If you don't declare your local variables with the var keyword, they are part of the global scope
var name = "Michael Jackson";
function showCelebrityName () {
    console.log (name);
}
function showOrdinaryPersonName () {    
    name = "Johnny Evers";
    console.log (name);
}
showCelebrityName (); // Michael Jackson
// name is not a local variable, it simply changes the global name variable
showOrdinaryPersonName (); // Johnny Evers
// The global variable is now Johnny Evers, not the celebrity name anymore
showCelebrityName (); // Johnny Evers
// The solution is to declare your local variable with the var keyword
function showOrdinaryPersonName () {    
    var name = "Johnny Evers"; // Now name is always a local variable and it will not overwrite the global variable
    console.log (name);
}
//    局部变量优先级大于全局变量
//如果在全局作用域中什么的变量在局部作用域中再次声明,那么在局部作用域中调用这个变量时,优先调用局部作用域中声明的变量: 
var name = "Paul";
function users () {
    // Here, the name variable is local and it takes precedence over the same name variable in the global scope
var name = "Jack";
// The search for name starts right here inside the function before it attempts to look outside the function in the global scope
console.log (name); 
}
users (); // Jack

全局变量
所有在函数外面声明的变量都处于全局作用域中。在浏览器环境中,这个全局作用域就是我们的Window对象(或者整个HTML文档)。

每一个在函数外部声明或者定义的变量都是一个全局对象,所以这个变量可以在任何地方被使用,例如:

// name and sex is not in any function
var myName = "zhou";
var sex = "male";//他们都处在window对象中
console.log(window.myName); //paul
console.log('sex' in window); //true

如果一个变量第一次初始化/声明的时候没有使用var关键字,那么他自动加入到全局作用域中。
function showAge(){
  //age初始化时没有使用var关键字,所以它是一个全局变量
  age = 20;
  console.log(age);
}showAge();  //20
console.log(age); //因为age是全局变量,所以这里输出的也是20

setTimeout中的函数是在全局作用域中执行的

setTimeout中的函数所处在于全局作用域中,所以函数中使用this关键字时,这个this关键字指向的是全局对象(Window):

var Value1 = 200;
var Value2 = 20;
var myObj = {
  Value1 : 10,
  Value2 : 1,  caleculatedIt: function(){
    setTimeout(function(){
      console.log(this.Value1 * this.Value2);
    }, 1000);
  }
}
myObj.caleculatedIt(); //4000

为了避免对全局作用域的污染, 所以一般情况下我们尽可能少的声明全局变量。 
变量提升(Variable Hoisting)
所以的变量声明都会提升到函数的开头(如果这个变量在这个函数里面)或者全局作用域的开头(如果这个变量是一个全局变量)。我们来看一个例子:

function showName () {
console.log ("First Name: " + name);
var name = "Ford";
console.log ("Last Name: " + name);
}showName (); 
// First Name: undefined
// Last Name: Ford
// The reason undefined prints first is because the local variable name was hoisted to the top of the function
// Which means it is this local variable that get calls the first time.
// This is how the code is actually processed by the JavaScript engine:
function showName () {
    var name; // name is hoisted (note that is undefined at this point, since the assignment happens below)
console.log ("First Name: " + name); // First Name: undefined
name = "Ford"; // name is assigned a value
// now name is Ford
console.log ("Last Name: " + name); // Last Name: Ford
}

函数声明会覆盖变量声明
如果存在函数声明和变量声明(注意:仅仅是声明,还没有被赋值),而且变量名跟函数名是相同的,那么,它们都会被提示到外部作用域的开头,但是,函数的优先级更高,所以变量的值会被函数覆盖掉。

// Both the variable and the function are named myName
var myName;?
function myName () {
console.log ("Rich");
}// The function declaration overrides the variable name
console.log(typeof myName); // function

但是,如果这个变量或者函数其中是赋值了的,那么另外一个将无法覆盖它:

// But in this example, the variable assignment overrides the function declaration
var myName = "Richard"; // This is the variable assignment (initialization) that overrides the function declaration.function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string

最后一点, 在严格模式下,如果没有先声明变量就给变量赋值将会报错!

Javascript 相关文章推荐
DOM 基本方法
Jul 18 Javascript
多浏览器支持的右下角浮动窗口
Apr 01 Javascript
Jquery插件 easyUI属性汇总
Jan 19 Javascript
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 Javascript
jquery实现一个简单好用的弹出框
Sep 26 Javascript
javascript实现当前页导航激活的方法
Feb 27 Javascript
浅谈javascript中for in 和 for each in的区别
Apr 23 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
Sep 15 Javascript
javascript中异常处理案例(推荐)
Oct 03 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
Mar 09 Javascript
Vue实现将数据库中带html标签的内容输出(原始HTML(Raw HTML))
Oct 28 Javascript
如何在JavaScript中创建具有多个空格的字符串?
Feb 23 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
Oct 24 #Javascript
jQuery设置div一直在页面顶部显示的方法
Oct 24 #Javascript
JS+CSS设置img在DIV中只显示Img垂直居中的部分
Oct 24 #Javascript
JS 获取滚动条高度示例代码
Oct 24 #Javascript
通过javascript把图片转化为字符画
Oct 24 #Javascript
js编写trim()函数及正则表达式的运用
Oct 24 #Javascript
原生JS实现加入收藏夹的代码
Oct 24 #Javascript
You might like
极典R601SW收音机
2021/03/02 无线电
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
PHP Cookei记录用户历史浏览信息的代码
2016/02/03 PHP
LINUX下PHP程序实现WORD文件转化为PDF文件的方法
2016/05/13 PHP
php自定义函数br2nl实现将html中br换行符转换为文本输入中换行符的方法【与函数nl2br功能相反】
2017/02/17 PHP
PHP从数组中删除元素的四种方法实例
2017/05/12 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
浅析PHP反序列化中过滤函数使用不当导致的对象注入问题
2020/02/15 PHP
Javascript实现的分页函数
2006/12/22 Javascript
理解JavaScript的caller,callee,call,apply
2009/04/28 Javascript
判断目标是否是window,document,和拥有tagName的Element的代码
2010/05/31 Javascript
基于JavaScript代码实现随机漂浮图片广告
2016/01/05 Javascript
JS+CSS实现鼠标经过弹出一个DIV框完整实例(带缓冲动画渐变效果)
2016/03/25 Javascript
jQuery.Validate表单验证插件的使用示例详解
2017/01/04 Javascript
vue中如何引入jQuery和Bootstrap
2017/04/10 jQuery
详解jquery插件jquery.viewport.js学习使用方法
2017/09/08 jQuery
Angularjs 手写日历的实现代码(不用插件)
2017/10/18 Javascript
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
npm全局模块卸载及默认安装目录修改方法
2018/05/15 Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
2019/09/10 Javascript
nodejs对mongodb数据库的增加修删该查实例代码
2020/01/05 NodeJs
node.js中 mysql 增删改查操作及async,await处理实例分析
2020/02/11 Javascript
python获得linux下所有挂载点(mount points)的方法
2015/04/29 Python
将Python代码打包为jar软件的简单方法
2015/08/04 Python
python使用matplotlib模块绘制多条折线图、散点图
2020/04/26 Python
pycharm 更改创建文件默认路径的操作
2020/02/15 Python
python爬虫中PhantomJS加载页面的实例方法
2020/11/12 Python
Myprotein丹麦官网:欧洲第一运动营养品牌
2019/04/15 全球购物
爱尔兰橄榄球店:Irish Rugby Store
2019/12/05 全球购物
北京某公司的.net笔试题
2014/03/20 面试题
《大禹治水》教学反思
2014/04/27 职场文书
公司股份转让协议书范本
2015/01/28 职场文书
如何在Python项目中引入日志
2021/05/31 Python
FP-growth算法发现频繁项集——构建FP树
2021/06/24 Python
Python+Matplotlib+LaTeX玩转数学公式
2022/02/24 Python
Python3的进程和线程你了解吗
2022/03/16 Python