JavaScript中变量提升和函数提升的意义理解

时间: 2018-03-22阅读: 2349标签: js知识

在ES6之前,js中是没有块级作用域的(ES6的块级作用域是指一对{}包括的内容, 花括号里就为一个级作用域),只存在全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分;函数提升只有函数声明中才发生。


现象:

1. 在JavaScript中变量和函数的声明会提升到最顶部执行。

2. 函数的提升高于变量的提升。

3. 函数内部如果用var声明了相同名称的外部变量,函数将不再向上寻找。

4. 匿名函数不会提升。

5. 不同<script>块中的函数互不影响。


1、变量提升:

console.log(global); // undefined
var global = 'global';
console.log(global); // global
 
function fn () {
  console.log(a); // undefined
  var a = 'aaa';
  console.log(a); // aaa
}
fn();

之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的:  

var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global
 
function fn () {
  var a; // 变量提升,函数作用域范围内
  console.log(a);
  a = 'aaa';
  console.log(a);
}
fn();


2、函数提升:

js中创建函数有两种方式:函数声明式和函数字面量式 

console.log(f1); // function f1() {}   
console.log(f2); // undefined  
function f1() {} //函数声明方式会被提升
var f2 = function() {} //函数字面量

只所以会有以上的打印结果,是由于js中的函数提升导致代码实际上是按照以下来执行的:  

function f1() {} // 函数提升,整个代码块提升到文件的最开始<br>     console.log(f1);   
console.log(f2);   
var f2 = function() {}


3、函数声明提升高于变量声明:

//同时声明变量a和函数a
var a;
function a() {} 
alert(typeof a); //显示的是"function",初步证明function的优先级高于var。
 
//先声明函数后声明变量,证明上边的例子不是function覆盖了变量
function a() {}
var a; 
alert(typeof a); //显示的仍是"function",而不是"undefined",即function的优先级高于var。
 
//声明了变量的同时赋值
function a() {}
var a = 1;
alert(typeof a); //number,此时不是function了。
//说明:"var a=1"相当于"var a;a=1",即先声明,后赋值,"a=1"相当于把a重新赋值了,自然就是number!


4、函数内部用var定义了和外部相同的变量,函数将不再向上找外部的变量 

var value = 'hello';
function show() {
  alert(value);
  if (!value) {
    var value = 'function';
  }
  alert(value);
}
show() //此处调用函数依次弹出 "undefined", "function"
 
//上例相当于var value = 'hello';
function show() {
  var value; //注意这行
  alert(value);
  if (!value) {
    value = 'function'; //这行去掉var
  }
  alert(value);
}
show()//1.如果上列中show内部定义value未用var,则会用到外部的变量,弹出"hello", "hello"。 
//2.如果函数内部未定义value,也能获取到外部的value值。


5、匿名函数不会向上提升

getName()
var getName = function () {
  alert('closule')
}
function getName() {
  alert('function')
}
getName()
 
//上边的代码相当于
function getName() { //函数向上提升
  alert('function')
}
getName()
var getName = function () {
  alert('closule')
}
getName()
 
//代码执行分别弹出 "function", "closule"


6、不同<script>块中的函数互不影响

<script>
  getName()
  var getName = function () {
    alert('closule')
  }
<script>
<script>
  function getName() {
    alert('function')
  }
<script>
 
//代码执行报错:TypeError: getName is not a function
//因为第一个<script>块中getName()函数未定义,匿名函数又不会向上提升





站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/534

关闭

js设备判断_判断移动端还是PC端?判断android还是ios?判断移动端浏览器类型?

js判断用户的浏览设备是移动设备还是PC?判断详细浏览器设备信息。判断微信、新浪、QQ打开。判断是android系统还是ios系统...

js基础_如何理解作用域和作用域链?

作用域外,无法引用作用域内的变量;离开作用域后,作用域的变量的内存空间会被清除,比如执行完函数或者关闭浏览器,作用域与执行上下文是完全不同的两个概念。我曾经也混淆过他们,但是一定要仔细区分。JavaScript代码的整个执行过程,分为两个阶段,代码编译阶段与代码执行阶段。

一眼看穿JS变量,作用域和内存问题

这篇文章将梳理下环境,作用域链,变量对象和活动对象,以及内存管理问题。基本类型和引用类型的值,我们都知道JS中的数据类型有两大类,基本数据类型和引用数据类型,下面从三个方面来解剖他们

Js输出方式有哪些?

在编写JavaScript代码的时候, 一定要记住每一句代码后面都需要添加一个分号, 并且这个分号必须是英文的分号,我们会发现有时候不写分号程序也能够运行, 这里并不是因为不需要分号, 而是浏览器自动帮助我们添加了分号

解密JavaScript执行上下文

首先我们先了解一下什么是执行上下文栈(Execution context stack)。分别展示了栈、堆和队列,其中栈就是我们所说的执行上下文栈;堆是用于存储对象这种复杂类型,我们复制对象的地址引用就是这个堆内存的地址

JavaScript中的行为委托

行为委托简单来说就是一种设计模式,不同于传统的构造函数的类式设计。这里每个例子会通过构造函数,class和行为委托来不同实现,不过不会评论class,是否使用class取决于你的观点。

base91 for javascript

原理和 base64 是一样的,ASCII 共有94个可打印字符,base64 使用了其中 64 个,base91 使用了 91 个。

前端与编译原理——用JS写一个JS解释器

说起编译原理,印象往往只停留在本科时那些枯燥的课程和晦涩的概念。作为前端开发者,编译原理似乎离我们很远,对它的理解很可能仅仅局限于“抽象语法树(AST)”。但这仅仅是个开头而已。编译原理的使用,甚至能让我们利用JS直接写一个能运行JS代码的解释器。

理解 JavaScript 执行栈

所有的 JS 代码在运行时都是在执行上下文中进行的。执行上下文是一个抽象的概念,JS 中有三种执行上下文:全局执行上下文,函数执行上下文,Eval 执行上下文。通常,我们的代码中都不止一个上下文,那这些上下文的执行顺序应该是怎样的?

JavaScript中的特殊运算,一些有趣的js等式

JavaScript中的特殊运算,字符,true,false参与运算结果会怎么样?打开控制台。这会允许你再你的浏览器里输入下面所有的代码,所以你可以实时的看到发生什么了。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!