深入理解JS中的变量及变量作用域
JS的变量有两种,“全局变量”和“局部变量”。
“全局变量”声明在函数外部,可供所有函数使用,(全局变量属于window)而“局部变量”声明在函数体内部,只能在定义该变量的函数体内使用。
1.全局变量:(1)直接在函数外部声明的变量 var a=3
(2)在任何位置上,声明变量时没有var关键字,而是直接赋值的变量均为全局变量 s=3
2.局部变量:(1)在函数内部声明的变量
(2)形参,参数变量天生就是局部变量
<script type="text/javascript">
function main() {
n = ;//这里的n为全局变量,可以被外部直接使用
}
main();
alert(n);
</script>
JS的作用域有两种,“全局作用域”和“函数作用域”。
1.全局作用域:可以在程序的任何位置被访问
2.函数作用域: 仅能在函数调用时,内部被访问
注意:在函数体内,局部变量的优先级高于全局变量。
网上有一个很具有代表性的例子,在函数体外部和内部都申明了相同名字的变量,变量的作用域问题,例子如下:
<script type="text/javascript">
var n = ;
function test() {
alert(n); //这里的n并不是全局变量,原因是函数体第四行声明了一个重名的局部变量n,
//如果把第四行n的声明注释掉,那么这里的显示1,为全局变量。
//所以得出结论:全局变量a被局部变量a覆盖了。
//说明了JS函数在test()在执行前,函数体内的变量a都指向了局部变量.
//但本行输出的a在执行过程中还没有被赋值,所以显示undefined。
n = ;
alert(n);
var n; //本行声明局部变量a
alert(n);
}
test();
alert(n);
</script>
上面代码的结果为:undefined 2 2 1; 原因就是函数体外部和内部都申明了相同名字的变量时,局部变量覆盖了全局变量。
外部怎么读取函数体内部的局部变量呢?
一般来说,只有函数体内部可以直接得到外部的全局变量,但是外部要得到函数体内部的局部变量是不行的。但是,通过在函数体内部再定义一个函数返回局部变量,再从外部调用函数就能实现了。
<script type="text/javascript">
function f1() {
var n = ;
function f2() {//在f1()内部再定义f2(),通过f2()访问f1()中的局部变量
alert(n);
}
return f2;//返回f1()局部变量n
}
var result = f1(); //在外部调用f1()函数,就能获取局部变量n的值
result(); // 10,即为n的值
</script>
函数中变量的声明提升
在程序执行前或函数调用前,将var声明的变量和function声明的函数提升到当前作用域的顶部集中创建。
请看下面的例子:
var v = "hello";
(function(){
console.log(v);
var v = "world";
})(); 结果为undefined
var v = "hello";
if(true){
console.log(v);
var v = "world";
} 结果为hello
上面的代码说明了3个问题:1,function作用域里的变量v遮盖了全局作用域变量v
2,在function作用域内,变量v的声明被提升了
3,javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构
上面的代码相当于:
var v = "hello";
(function(){
var v; //declaration hoisting
console.log(v);
v = "world";
})();
总结:当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明。
(function(){
var a = "";
var f = function(){};
var b = "";
var c = "";
})();
变量a,f,b,c的声明会被提升到函数作用域的最前面,如下
(function(){
var a,f,b,c;
a = "";
f = function(){};
b = "";
c = "";
})();
请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
(function(){
//var f1,function f2(){}; //声明提升,被隐式提升的声明
f1(); //ReferenceError: f1 is not defined
f2();
var f1 = function(){};
function f2(){}
})();
上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。
深入理解JS中的变量及变量作用域的更多相关文章
- [js]js的惰性声明, js中声明过的变量(预解释),后在不会重新声明了
js的惰性声明, js中声明过的变量(预解释),后在不会重新声明了 fn(); // 声明+定义 js中声明过一次的变量,之后在不会重新声明了 function fn() { console.log( ...
- js中三种定义变量 const, var, let 的区别
js中三种定义变量的方式const, var, let的区别 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始化 ...
- 深入探究js中的隐式变量声明
前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
- 如何更好的理解js中的this,分享2段有意思的代码
关于js中this的浅析,大家可以点击[彻底理解js中this的指向,不必硬背]这篇博客了解. 今天遇到2段比较有意思的代码. ----------------第一段----------------- ...
- 图文结合深入理解 JS 中的 this 值
图文结合深入理解 JS 中的 this 值 在 JS 中最常见的莫过于函数了,在函数(方法)中 this 的出现频率特别高,那么 this 到底是什么呢,今天就和大家一起学习总结一下 JS 中的 th ...
- 深度理解js中var let const 区别
首先要理解js中作用域的概念 作用域:指的是一个变量的作用范围 1.全局作用域 直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个 ...
- 如何理解js中的this和实际应用中需要避开哪些坑
this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { console.log(this) } 'use strict' f ...
- 深入理解JS中的对象(三):class 的工作原理
目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...
- 深入理解Js中的this
深入理解Js中的this JavaScript作用域为静态作用域static scope,但是在Js中的this却是一个例外,this的指向问题就类似于动态作用域,其并不关心函数和作用域是如何声明以及 ...
随机推荐
- 多线程(Thread,Runnable)
一.多线程. 1.进程:一个正在执行的程序叫做进程. 每一个进程的执行都有一个执行顺序,这个顺序就是一个执行的路径,或者叫做一个控制单元. 2.线程:就是上述进程中的一个独立控制单元, 线程在控制着进 ...
- 超详细从零记录Hadoop2.7.3完全分布式集群部署过程
超详细从零记录Ubuntu16.04.1 3台服务器上Hadoop2.7.3完全分布式集群部署过程.包含,Ubuntu服务器创建.远程工具连接配置.Ubuntu服务器配置.Hadoop文件配置.Had ...
- OSPF基础介绍
OSPF基础介绍 一.RIP的缺陷 1.以跳数评估的路由并非最优路径 2.最大跳数16导致网络尺度小 3.收敛速度慢 4.更新发送全部路由表浪费网络资源 二.OSPF基本原理 1.什么是OSPF a& ...
- C#网络编程之进程管理
这里是视频讲解地址: 这里是代码: using System; using System.Collections.Generic; using System.Linq; using System.Ne ...
- Linux记录-清空文件内容
$ : > filename $ > filename $ echo "" > filename $ echo > filename $ cat /dev/ ...
- JAVA记录-WebService开发部署
JWS.Axis2.cxf 1.下载axis2.war和axis2.bin.zip 2.将axis2.war包部署到Tomcat下,启动Tomcat测试:http://localhost:8089/a ...
- Linux记录-shell一行代码杀死进程(收藏)
ps -ef |grep hello |awk '{print $2}'|xargs kill -9
- 03-Windows Server 2016 IIS的安装与配置
1. 打开服务器管理器,点击[添加角色和功能选项]. 2. 进入“添加角色和功能向导”页面,点击下一步. 3. 安装类型选择[基于角色或基于功能的安装],点击下一步. 4. 进入服务器选 ...
- postgresql时间处理
时间取到截取 例:select date_trunc('second', "reportTime") from travel_message limit 10; 结果: 他人博客: ...
- 【转】Robot Framework作者建议如何选择自动化测试框架
原文:http://www.infoq.com/cn/news/2012/06/robot-author-suggest-autotest 软件自动化测试,作为手工测试的替代,越来越受到关注.Pekk ...