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

 更新时间:2013年10月24日 16:22:57   作者:  
在javascript中, 理解变量的作用域以及变量提升是非常有必要的。这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解

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

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

局部变量(处于函数级别的作用域)
不像其他对面对象的编程语言(比方说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

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

相关文章

  • HTML5+Canvas调用手机拍照功能实现图片上传(上)

    HTML5+Canvas调用手机拍照功能实现图片上传(上)

    这篇文章主要为大家详细介绍了HTML5+Canvas,和jquery技术,调用手机拍照功能实现图片上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • JS实现单例模式的N种方案

    JS实现单例模式的N种方案

    JS实现单例模式的多种方案 ,本文稍加总结,列出了6种方式与大家分享,大体上将内容分为了ES5(Function)与ES6(Class)实现两种部分,对js单例模式相关知识感兴趣的朋友跟随小编一起看看吧
    2022-09-09
  • javascript-简单的日历实现及Date对象语法介绍(附图)

    javascript-简单的日历实现及Date对象语法介绍(附图)

    主要是对Date对象的使用,首先回忆一下Date对象的参数及方法,代码如下,感兴趣的朋友可以参考下哈
    2013-05-05
  • bootstrap fileinput插件实现预览上传照片功能

    bootstrap fileinput插件实现预览上传照片功能

    这篇文章主要介绍了bootstrap fileinput插件实现预览上传照片功能,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 基于JavaScript实现十五拼图代码实例

    基于JavaScript实现十五拼图代码实例

    这篇文章主要介绍了基于JavaScript实现十五拼图代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • JS array数组检测方式解析

    JS array数组检测方式解析

    这篇文章主要介绍了JS array数组检测方式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • js中对函数设置默认参数值的3种方法

    js中对函数设置默认参数值的3种方法

    这篇文章主要介绍了js中对函数设置默认参数值的3种方法吗,3种方法都具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-10-10
  • JavaScript生成一个不重复的ID的方法示例

    JavaScript生成一个不重复的ID的方法示例

    这篇文章主要介绍了JavaScript生成一个不重复的ID的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • javascript实现用户点击数量统计

    javascript实现用户点击数量统计

    本文主要javascript实现用户点击数量统计的方法进行详细介绍,具有很好的参考价值,需要的朋友一起来看下吧
    2016-12-12
  • 详解Webpack实战之构建 Electron 应用

    详解Webpack实战之构建 Electron 应用

    本篇文章主要介绍了Webpack实战之构建 Electron 应用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12

最新评论