《JavaScript应用程序设计》一一2.7 变量提升

2.7 变量提升

变量提升是指函数中的所有变量声明会在函数执行时被“提升”至函数体顶端,这仅仅是从非技术角度来阐述的,至少从开发者看来实际效果如此。
JavaScript的执行环境构建分为声明阶段和执行阶段。在声明阶段JavaScript引擎为所有变量与函数声明创建标识符,可以将此阶段看作是对运行环境的前期配置。到了执行阶段,函数均已被定义,但所有变量的值均未定义,例如:

var x = 1;

(function () {
  console.log(x);
  var x = 2;
}());

我相信大部分人都会认为console.log(x)中x的值为1,这算是JavaScript中一个典型的代码陷阱。在声明阶段仅有函数被定义,此时在作用域内外x的值都为undefined,而在执行到console.log()语句时,内部作用域中的x虽被定义但还未被赋值,所以其值仍为undefined,实际上JavaScript是这样解释代码的:

var x = 1;

(function () {
  var x; // Declaration is hoisted and x is undefined.
  console.log(x);
  x = 2; // Initialization is still down here.
}());

函数的“提升”会与变量稍显不同,此例中,名为number的函数标识符与函数体会同时被“提升”,而相比较前面的例子,对变量x的赋值操作未被“提升”。

test('Function declaration hoisting', function () {
  function number() {
    return 1;
  }

  (function () {
    equal(number(), 2, 'Inner scope wins.');

    function number() {
      return 2;
    }
  }());

  equal(number(), 1, 'Outer scope still works.');
});

上述代码等同于:

test('Function declaration hoisted.', function () {
  function number() {
    return 1;
  }

  (function () {
    function number() {
      return 2;
    }

    equal(number(), 2, 'Inner scope wins.');
  }());

  equal(number(), 1, 'Outer scope still works.');
});

不过函数表达式则另当别论,因为它们仅仅是变量声明的另一种形式,所以其提升行为与变量提升行为等同。

test('Function expression hoisting', function () {
  function number() {
    return 1;
  }

  (function () {
    try {
      number();
    } catch (e) {
      ok(true, 'number() is undefined.');
    }

    var number = function number() {
      return 2;
    }

    equal(number(), 2, 'number() is defined now.');
  }());

  equal(number(), 1, 'Outer scope still works.');
});

在上述示例中,名为Number的变量在声明阶段会被提升,但它所对应的函数体则不会被提升,因为Number仅仅是函数表达式而非函数声明。它的赋值操作直到运行阶段才会被执行,代码等同于:

test('Function Expression Hoisted', function () {
  function number() {
    return 1;
  }

  (function () {
    var number; // Declaration initialized to undefined.

    try {
      number();
    } catch (e) {
      ok(true, 'number() is undefined.');
    }

    number = function number() {
      return 2;
    }

    equal(number(), 2, 'number() is defined now.');
  }());

  equal(number(), 1, 'Outer scope still works.');
});

注意: 这几个例子是为了告诉你,在进行与作用域有关的操作时,要谨记变量提升的规律。如果你有将所有变量声明放置在函数顶端的编码习惯,或者你对待函数向来都是先声明再使用,那么你完全可以忽略它们。

时间: 2024-10-28 05:56:17

《JavaScript应用程序设计》一一2.7 变量提升的相关文章

《JavaScript应用程序设计》一一2.2 函数声明

2.2 函数声明 在JavaScript中有多种定义函数的方法,不同方法各有优缺点. function foo() { /* Warning: arguments.callee is deprecated. Use with caution. Used here strictly for illustration. */ return arguments.callee; } foo(); //=> [Function: foo] 在这段代码中,foo()是一个函数声明.正如在"变量提升&q

JavaScript中变量提升 Hoisting_javascript技巧

因为我在写这文章的时候,百度里找资料,找到了园友的一篇文章,写的很好,可是我写了又不想放弃,所以就在里面拿了很多东西过来!~~ [翻译]JavaScript Scoping and Hoisting 希望得到大家谅解. 一.案发现场 我们先看一段很简单的代码: 复制代码 代码如下: var v='Hello World'; alert(v); 这个没有疑问吧,弹出"Hello World".OK,我们继续. 我们在看一段Code: 复制代码 代码如下: var v='Hello Wor

javascript中的变量作用域以及变量提升详细介绍_javascript技巧

变量作用域"一个变量的作用域表示这个变量存在的上下文.它指定了你可以访问哪些变量以及你是否有权限访问某个变量." 变量作用域分为局部作用域和全局作用域. 局部变量(处于函数级别的作用域)不像其他对面对象的编程语言(比方说C++,Java等等),javascript没有块级作用域(被花括号包围的):当是,javascript有拥有函数级别的作用域,也就是说,在一个函数内定义的变量只能在函数内部访问或者这个函数内部的函数访问(闭包除外,这个我们过几天再写个专题). 函数级别作用域的一个例子

深入理解Javascript作用域与变量提升_javascript技巧

下面的程序是什么结果? 复制代码 代码如下: var foo = 1;function bar() { if (!foo) {  var foo = 10; } alert(foo);}bar(); 结果是10: 那么下面这个呢? 复制代码 代码如下: var a = 1;function b() { a = 10; return; function a() {}}b();alert(a); 结果是1. 吓你一跳吧?发生了什么事情?这可能是陌生的,危险的,迷惑的,同样事实上也是非常有用和印象深刻

JavaScript高级程序设计(第3版)学习笔记8 js函数(中)_基础知识

6.执行环境和作用域 (1)执行环境(execution context):所有的JavaScript代码都运行在一个执行环境中,当控制权转移至JavaScript的可执行代码时,就进入了一个执行环境.活动的执行环境从逻辑上形成了一个栈,全局执行环境永远是这个栈的栈底元素,栈顶元素就是当前正在运行的执行环境.每一个函数都有自己的执行环境,当执行流进入一个函数时,会将这个函数的执行环境压入栈顶,函数执行完之后再将这个执行环境弹出,控制权返回给之前的执行环境. (2)变量对象(variable ob

JavaScript高级程序设计(第3版)学习笔记7 js函数(上)_基础知识

变量类型 在说函数之前,先来说说变量类型. 1.变量:变量在本质上就是命名的内存空间. 2.变量的数据类型:就是指变量可以存储的值的数据类型,比如Number类型.Boolean类型.Object类型等,在ECMAScript中,变量的数据类型是动态的,可以在运行时改变变量的数据类型. 3.变量类型:是指变量本身的类型,在ECMAScript中,变量类型就只有两种:值类型和引用类型.当变量的数据类型是简单数据类型时,变量类型就是值类型,当变量的数据类型是对象类型时,变量类型就是引用类型.在不引起

《JavaScript高级程序设计》学习笔记

系统学习JS, 从<JavaScript高级程序设计>入门,通过学习jQuery或者angularJS源码来进阶. 第1章 JavaScript简介 1.JS问世的目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作, 由Netscape主导开发,那时候微软的IE还不能独领风骚.最初叫做LiveScript,当时媒体热炒Java,于是改名为JavaScript. JavaScript和ECMAScript通常指同一门语言,但是,JavaScript是ECMA-262标准的实现和扩展

JavaScript高级程序设计(第三版)学习笔记6、7章_javascript技巧

第6章面向对象的程序设计 对象 1.数据属性 configurable表示能否通过delete删除属性从而重新定义属性能否修改属性的特性或能否把属性修改为访问器属性默认为true enumerbale表示能否通过for-in访问属性默认true writable表示能否修改属性值默认true value数据存储位置默认undefined 修改默认属性特性Object.defineProperty()接收三个参数属性所在对象属性名描述符对象描述符对象属性必须是configurable.enumer

JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型_基础知识

ECMAScript是一种动态类型的语言,构建于5种简单数据类型(Undefined.Null.Boolean.Number.String)和一种复杂数据类型(Object)的基础之上.这篇文章就来复习一下简单数据类型,我会尽量从编程实践的角度来描述,下面代码运行环境为FireFox 14.0.1. 简单数据类型 简单数据类型 取值 Undefined undefined(只有一个值) Null null(只有一个值) Boolean true|false(只有两个值) Number 数值 St