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 相关文章推荐
Javascript实例教程(19) 使用HoTMetal(6)
Dec 23 Javascript
javascript中的有名函数和无名函数
Oct 17 Javascript
Dreamweaver jQuery智能提示插件,支持版本提示,支持1.6api
Jul 31 Javascript
jQuery中serializeArray()与serialize()的区别实例分析
Dec 09 Javascript
jQuery ready()和onload的加载耗时分析
Sep 08 Javascript
$.browser.msie 为空或不是对象问题的多种解决方法
Mar 19 Javascript
用js将long型数据转换成date型或datetime型的实例
Jul 03 Javascript
vuejs+element-ui+laravel5.4上传文件的示例代码
Aug 12 Javascript
vue使用drag与drop实现拖拽的示例代码
Sep 07 Javascript
详解如何使用 vue-cli 开发多页应用
Dec 16 Javascript
VUE v-model表单数据双向绑定完整示例
Jan 21 Javascript
全面解析js中的原型,原型对象,原型链
Jan 25 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
CI框架中zip类应用示例
2014/06/17 PHP
php天翼开放平台短信发送接口实现方法
2014/12/22 PHP
Apache启动报错No space left on device: AH00023该怎么解决
2015/10/16 PHP
JavaScript怎么判断图片是否加载完成以便获取其尺寸
2014/05/08 Javascript
JQuery中ajax方法访问web服务实例
2015/07/18 Javascript
JS基于myFocus库实现各种功能的tab选项卡切换效果
2015/09/19 Javascript
跟我学习javascript的函数调用和构造函数调用
2015/11/16 Javascript
基于JavaScript实现TAB标签效果
2016/01/12 Javascript
移动端js触摸事件详解
2016/09/18 Javascript
JS简单实现自定义右键菜单实例
2017/05/31 Javascript
深入理解JavaScript创建对象的多种方式以及优缺点
2017/06/01 Javascript
Vue.js搭建移动端购物车界面
2020/06/28 Javascript
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
JavaScript实现单图片上传并预览功能
2019/09/30 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式功能
2020/04/09 Javascript
学习python处理python编码问题
2011/03/13 Python
Python2和Python3之间的str处理方式导致乱码的讲解
2019/01/03 Python
Python如何获得百度统计API的数据并发送邮件示例代码
2019/01/27 Python
简单了解python gevent 协程使用及作用
2019/07/22 Python
在Python中使用MySQL--PyMySQL的基本使用方法
2019/11/19 Python
Python 统计位数为偶数的数字代码详解
2020/03/15 Python
pycharm 对代码做静态检查操作
2020/06/09 Python
基于Python实现2种反转链表方法代码实例
2020/07/06 Python
英国最大的高品质珠宝和手表专家:Goldsmiths
2017/03/11 全球购物
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
美国主要的特色咖啡和茶公司:Peet’s Coffee
2020/02/14 全球购物
神路信息Java面试题目
2013/03/31 面试题
师范教师大学生职业生涯规划范文
2014/01/05 职场文书
环保倡议书100字
2014/05/15 职场文书
保护环境标语
2014/06/09 职场文书
社区党的群众路线教育实践活动总结材料
2014/10/31 职场文书
2014小学教师个人工作总结
2014/11/10 职场文书
初婚初育证明范本
2015/06/18 职场文书
个人催款函范文
2015/06/23 职场文书
预备党员表决心的话
2015/09/22 职场文书