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. arm裸机通过uboot运行hello world程序测试结果

    开发板EasyARM i.MX280A CPU:arm926ejs helloworld程序使用的编译器 (1)arm-fsl-linux-gnueabi-gcc  version gcc4.4.4 ...

  2. 决策树--信息增益,信息增益比,Geni指数的理解

    决策树 是表示基于特征对实例进行分类的树形结构       从给定的训练数据集中,依据特征选择的准则,递归的选择最优划分特征,并根据此特征将训练数据进行分割,使得各子数据集有一个最好的分类的过程.   ...

  3. Struts2中遇到的问题

    问题1: 最近在学习的时候用到了Struts2.5,在一系列操作之后Tomcat部署成功了,然而之后在测试的时候却出现了问题,网页无法正常响应,并且报出了Wrong method was define ...

  4. 如何解决win7系统无法运行cmd命令提示符

    如何解决win7系统无法运行cmd命令提示符   CMD命令可以帮助我们很快的执行所需要的程序命令,可以查询系统中很多的信息和解决系统很多的故障,对我们来说非常方便,但是最近有用户反馈自己win7电脑 ...

  5. Spark简介安装和简单例子

    Spark简介安装和简单例子 Spark简介 Spark是一种快速.通用.可扩展的大数据分析引擎,目前,Spark生态系统已经发展成为一个包含多个子项目的集合,其中包含SparkSQL.Spark S ...

  6. Spring面向切面编程AOP(around)实战

    spring aop的环绕通知around功能强大,我们这里就不细说,直接上代码,看着注释就能明白 需要的可以点击下载源码 1.如果使用注解的方式则需要先创建个注解类 package com.mb.a ...

  7. Python面向对象-day07

    写在前面 上课第七天,打卡: 时间的高效利用: 前言: 今天egon老师补充了下 is 和 == 的区别,整理如下:Python中变量的属性以及判断方法 一.面向过程和面向对象 - 1.面向过程 核心 ...

  8. pd.qcut, pd.cut, df.groupby()等在分组和聚合方面的应用

    pd.qcut, pd.cut, df.groupby()等在分组和聚合方面的应用 量化交易里, 需要进行大量的分组和统计, 以方便自己处优势的位置/机会. 比如对股价进行趋势分析, 波动性分析, 量 ...

  9. HTML5 元素拖拽实现 及 jquery.event.drag插件

    如上图片: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" c ...

  10. android 短信拦截

    android 4+版本需要用户主动添加broadReceiver 1.清单文件 <manifest xmlns:android="http://schemas.android.com ...