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. ElasticSearch 索引整体迁移方案

    以下都是经过实战验证过的!!! [前提]使用相同的版本 ElasticSearch-5.5.1,只不过是在不同的服务器之间且重跑数据相对来说代价比较高,这种情况下就可以使用一下这种方式对索引整体迁移 ...

  2. python3简单实现微信爬虫

    Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...

  3. PLSQL Developer 连接Linux 下Oracle的安装与配置

    一.下载 下载地址:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html 这是Ora ...

  4. Spark记录-SparkSQL远程操作MySQL和ORACLE

    1.项目引入mysql和oracle驱动 2.将mysql和oracle驱动上传到hdfs 3.远程调试源代码如下: import org.apache.spark.sql.SQLContext im ...

  5. java自带BASE64工具进行图片和字符串转换【转】

    java自带BASE64工具进行图片和字符串转换 import java.io.File; import java.io.FileInputStream; import java.io.FileOut ...

  6. 怎样动态地插入不会暴露给用户的JS文件

    也是无意间看见的,以前想过这个问题,但是没多想,今天看到这段代码豁然开朗 (function() { var dynamicScript = document.createElement('scrip ...

  7. linux4.10.8 内核移植(二)---初步裁剪、分区修改和文件系统

    一.初步裁剪 在内核根目录下 执行: make menuconfig 1.1 system type裁剪 选择 SAMSUNG S3C24XX SoCs Support 进入其中,这里是配置我们的单板 ...

  8. 20155332 2016-2017-2 《Java程序设计》第5周学习总结

    学号 2016-2017-2 <Java程序设计>第X周学习总结 教材学习内容总结 1.Java中的所有不正常类都继承于Throwable类.Throwable主要包括两个大类,一个是Er ...

  9. Nginx 内核优化

    内核参数的优化示例: /etc/sysctl.conf net.ipv4.tcp_max_tw_buckets = // timewait的数量,默认是180000. net.ipv4.ip_loca ...

  10. 使用Sphinx生成本地的Python帮助文档

    第一步:安装Sphinx 首先我们需要安装Sphinx,如果已经安装了Anaconda,那么只需要使用如下命令即可安装,关于其中的参数 -c anaconda,可以在链接[1]中查看: conda i ...