javascript中的变量作用域以及变量提升
在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
// 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中的变量作用域以及变量提升详细介绍
在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...
- 【转载】【翻译】JavaScript Scoping and Hoisting--JS作用域和变量提升的探讨
原文链接:http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting 你知道下面的JavaScript代码执行后会aler ...
- JavaScript中var和this定义变量的区别
JavaScript中var和this定义变量的区别 在js中声明变量时可以使用var和this,但使用this的有很大一部分参考书是没有的,经过查阅相关资料总结如下: 用var和this声明变量,存 ...
- Javascript中闭包的作用域链
作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...
- Python 再谈变量作用域与变量引用
再谈变量作用域与变量引用 by:授客 QQ:1033553122 module3.py #!/usr/bin/env python # -*- coding:utf-8 -*- __author_ ...
- javascript中的this作用域详解
javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...
- 解读JavaScript中的Hoisting机制(js变量声明提升机制)
hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ...
- JavaScript 变量作用域和声明提升
一.变量作用域 说到这个概念,不有自主的想到this,scope 这两个关键字. JavaScript的this总是指向一个明确的对象,这个对象是在执行的时候动态绑定的.通俗的说就是谁调用我,我的th ...
- JavaScript中是如何定义私有变量的
前言 JavaScript并不像别的语言,能使用关键字来声明私有变量. 我了解的JavaScript能用来声明私有变量的方式有两种,一种是使用闭包,一种是使用WeakMap. 闭包 闭包的描述有很多种 ...
随机推荐
- C# Web应用调试开启外部访问
在用C#开发Web应用时有个痛点,就是本机用VS开启Web应用调试时外部机器无法访问此Web应用.这里将会介绍如何通过设置允许局域网和外网机器访问本机的Web应用. 目录 1. 设置内网访问 2. 设 ...
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 无法向会话状态服务器发出会话状态请求.请确保 ASP.NET State Ser ...
- CENTOS 6.5 平台离线安装 Apache2.4
一.下载Apache 2.4 http://httpd.apache.org/download.cgi http://mirrors.cnnic.cn/apache//httpd/httpd-2.4. ...
- Ubuntu 16.10 安装byzanz截取动态效果图工具
1.了解byzanz截取动态效果图工具 byzanz能制作文件小,清晰的GIF动态效果图,不足就是,目前只能通过输入命令方式来录制. byzanz主要的参数选项有: -d, --duration=SE ...
- ZKWeb网页框架1.2正式发布
发行日志 https://github.com/zkweb-framework/ZKWeb/blob/master/ReleaseNotes/ReleaseNote.1.2.md 主要改动 更新 ZK ...
- servlet 简介,待完善
什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③ 这个在服务器端运行,用以处理客户端的请求 Servlet相关包的介绍--javax. ...
- nginx服务器安装及配置文件详解
nginx在工作中已经有好几个环境在使用了,每次都是重新去网上扒博客,各种编译配置,今天自己也整理一份安装文档和nginx.conf配置选项的说明,留作以后参考.像负载均衡配置(包括健康检查).缓存( ...
- SAP CRM 显示消息/在消息中进行导航
向用户展示消息,在任何软件中都是十分重要的. 在SAP CRM WEB UI中展示消息,不是一项很难的任务,只需要创建消息并在之后调用方法来显示它 消息类和消息号: 我在SE91中创建了如下的消息类和 ...
- Web 前端攻防(2014版)
在百度 FEX 团队时写的.有次让我写点前端开发中注意的安全规范,结果写着写着就跑题了,写了一堆纯前端实现的攻击方式...当然还有防范措施. 文章就懒得粘过来了~ 直接贴个地址算了:) http:// ...
- 浅谈命令查询职责分离(CQRS)模式
在常用的三层架构中,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.在一些业务逻辑简单的系统中可能没有什么问题,但是随着系统逻辑变得复杂,用户增多,这种设计就会出现一些性能 ...