深入理解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的指向问题就类似于动态作用域,其并不关心函数和作用域是如何声明以及 ...
随机推荐
- 如何将Anaconda更新到想要的python版本
最近用Anaconda比较多,因为它里面的包很全啊.如果下个原生的python,要用的时候得自己一个个装. 但是有些包又互相依赖,一个个装的时候实在很抓狂.懒人就想到了anaconda这种套装集合了. ...
- 02-HTML5新的input属性
本节重点 HTML5 拥有多个新的表单输入类型.这些新特性提供了更好的输入控制和验证 本节介绍新的输入类型: date datetime datetime-local email month numb ...
- Codeforce Div-2 985 C. Liebig's Barrels
http://codeforces.com/contest/985/problem/C C. Liebig's Barrels time limit per test 2 seconds memory ...
- centos6.5环境下安装zk
第一步:先下载安装包,解压. 第二步:进去根目录,创建data文件夹 mkdir data 第三步:进去conf文件夹,修改 zoo_sample.cfg 的名字 mv zoo_sam ...
- div中让内容能不换行就尽量不换行.【纯原】
div中让内容能不换行就尽量不换行,部分左对齐,部分右对齐. <html> <head> <title>九歌·少司命</title> <style ...
- 【C++ STL】Set和Multiset
1.结构 set和multiset会根据特定的排序原则将元素排序.两者不同之处在于,multisets允许元素重复,而set不允许重复. 只要是assignable.copyable.comparab ...
- 浅谈分词算法(4)基于字的分词方法(CRF)
目录 前言 目录 条件随机场(conditional random field CRF) 核心点 线性链条件随机场 简化形式 CRF分词 CRF VS HMM 代码实现 训练代码 实验结果 参考文献 ...
- 〖C语言学习笔记 〗(二) 数据类型
前言 本文为c语言的学习笔记,很多只是留下来占位的 数据类型 助记:变量就是在内存中挖个坑并给这个坑命名,而数据类型就是挖内存的坑的尺寸 基础类型 整数类型: short int int long i ...
- Linux 4.10.8 根文件系统制作(三)---制作yaffs文件系统
这里直接用的是韦东山提供的工具. yaffs文件系统是专门用于nandflash的文件系统 我们前面已经下载了yaffs 的源码,也做了文件系统目录的构建. 在yaffs2的源码目录中有一个utils ...
- Postfix邮件服务 - DNS配置
DNS 域名系统服务器 IP 与 域名之间解析 :提供分层的域名解析 服务:bing 伯克利加州大学 应用最广的域名服务系统: bind 主要分为 主配置文件 和 域数据记录文件 yum 安装: yu ...