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中的变量及变量作用域的更多相关文章

  1. [js]js的惰性声明, js中声明过的变量(预解释),后在不会重新声明了

    js的惰性声明, js中声明过的变量(预解释),后在不会重新声明了 fn(); // 声明+定义 js中声明过一次的变量,之后在不会重新声明了 function fn() { console.log( ...

  2. js中三种定义变量 const, var, let 的区别

    js中三种定义变量的方式const, var, let的区别 1.const定义的变量不可以修改,而且必须初始化. 1 const b = 2;//正确 2 // const b;//错误,必须初始化 ...

  3. 深入探究js中的隐式变量声明

    前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...

  4. 浅谈JS中 var let const 变量声明

    浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...

  5. 如何更好的理解js中的this,分享2段有意思的代码

    关于js中this的浅析,大家可以点击[彻底理解js中this的指向,不必硬背]这篇博客了解. 今天遇到2段比较有意思的代码. ----------------第一段----------------- ...

  6. 图文结合深入理解 JS 中的 this 值

    图文结合深入理解 JS 中的 this 值 在 JS 中最常见的莫过于函数了,在函数(方法)中 this 的出现频率特别高,那么 this 到底是什么呢,今天就和大家一起学习总结一下 JS 中的 th ...

  7. 深度理解js中var let const 区别

    首先要理解js中作用域的概念 作用域:指的是一个变量的作用范围 1.全局作用域 直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个 ...

  8. 如何理解js中的this和实际应用中需要避开哪些坑

    this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { console.log(this) } 'use strict' f ...

  9. 深入理解JS中的对象(三):class 的工作原理

    目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...

  10. 深入理解Js中的this

    深入理解Js中的this JavaScript作用域为静态作用域static scope,但是在Js中的this却是一个例外,this的指向问题就类似于动态作用域,其并不关心函数和作用域是如何声明以及 ...

随机推荐

  1. csp20151203画图 解题报告和易错地方

    Solution: dfs 对于dfs: //遇到map[u][v]==c,则不用再搜    //因为通过(u,v)到达的其它点(p,q),    //之前从(u,v)开始肯定能到达(p,q),(p, ...

  2. Solr各个版本重大变化之安装方式【请别违背规律】

    这里主要讲安装方式的变化 4.x~5.x的变化 这是4.x的安装方式,大家都熟知,在我看来未免繁琐了一点. 或许官方也感觉繁琐了,于是5.x有个最大的改变.↓ 现在Solr是一个独立的服务器 什么叫S ...

  3. 'RegAsm.exe' 不是内部或外部命令

    我想从cmd运行regasm.exe.它在c:\windows \Microsoft.net\framework\2.057 中可用 我喜欢这个c:\ regasm.exe 它给予 regasm无法识 ...

  4. .NET中26个优化性能方法

    1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源.ASP.NET中提供了连接池( ...

  5. ajaxSubmit 提交form 表单

    $(document).on('click','#submit_title_btn',function(){ var title = $("#title").val(); if ( ...

  6. 记一次B站答题经历

    第一题部分:社区规范卷 --------- ------------ 第二题:社区规范第二部分 -------------------- 第三部分自由选择题 --------------------- ...

  7. Database in BioInformation

    很多数据库都可以通过下面的网站下载:http://annovar.openbioinformatics.org/en/latest/user-guide/download/ 一.NHLBI-ESP(E ...

  8. H5静态资源本地化实践

    现在很多app都是通过webview内嵌H5的页面,这种方式的好处就是无需发版就能更新线上的内容,而且可以做到多平台的统一开发,节约开发成本.但是这种模式也带来了一定的问题,web开发很大程度依赖于网 ...

  9. Kettle 中转换(transformation)的执行过程

    1,Spoon.java的main方法是整个Kettle运行的入口.当打开Kettle的设计器界面后,可以在其中设计作业和转换.这里讨论转换的执行过程. 2,设计好一个转换后,转换保存的本地文件是 . ...

  10. Sql Server数据库资料收集

    1.表分区 http://www.cnblogs.com/huangxincheng/p/3565755.html 2.MVP教程地址:http://www.cnblogs.com/lyhabc/p/ ...