var foo = 1; 
function bar() { 
    if (!foo) { 
        var foo = 10; 
    } 
    alert(foo); 

bar();//解释:js没有块级作用域,if switch while等不会有块级作用域

如果你对foo的值实际上为"10"而感到诧异的话,再看一下下面这个例子:

var a = 1; 
function b() { 
    a = 10; 
    return; 
    function a() {} 

b(); 
alert(a);
发现浏览器会弹出alert(1)。
//解释:第一点是函数声明的提升会把函数的实现都提升到作用域的最顶级,上面的函数b相当于
function b() { 
  function a() {} 
    a = 10; 
    return; 
    

第二点是:这样的话,我们在b函数里面定义了一个a函数,a的作用域是在b函数的内部而非全局,这是对a的赋值相当于把a函数替换,作用域并不发生变化,相当于用var定义了一个a变量;所以在b函数外面输出a的时候只会去访问全局的a;
//var a = 1; 
function b() { 
    a = 10; 
    return; 
    function a() {} 

b(); 
alert(a);//报错a is undefined
另外:如果这里的a函数不是函数声明式定义的而是变量式定义的,变量提升而函数实现并不会提升:如下:
var a = 1; 
function b() { 
    a = 10; 
    return; 
    a=function () {} //此处的a是全局的变量

b(); 
alert(a);//10
如果是这样的话
var a = 1; 
function b() { 
    a = 10; 
    return; 
  var a=function () {} //此处的a是局部变量

b(); 
alert(a);//1
等价于这个:
var a = 1; 
function b() { 
   var a;
    a = 10; 
    return; 
  a=function () {} //此处的a是局部变量

b(); 
alert(a);//1
可以发现,声明语句中的赋值部分并没有被提升声明,只有名称被提升了。两种函数声明方式:
function test() { 
    foo(); // TypeError "foo is not a function" 
    bar(); // "this will run!" 
    var foo = function () { // function expression assigned to local variable 'foo' 
        alert("this won't run!"); 
    } 
    function bar() { // function declaration, given the name 'bar' 
        alert("this will run!"); 
    } 

test();
这个例子中,只有包含函数体的函数声明会被提升声明。foo虽然会被提升声明,但是函数体却在执行中被赋值。以上就是提升声明时机的基本概念,看起来一点也不复杂。

Name resolution order(JavaScript中名称解析顺序)

名称解析顺序有4步,一般来说,如果一个名称已经被定义了,它就不会被另一个具有同名称的属性所覆盖。这也就意味着,函数声明会比变量声明优先。并不是名称的赋值操作不会被执行,只是说声明部分被忽略了而已。有些例外:
  • 原生变量arguments特立独行,包含了传递到函数中的参数。如果自定义以arguments为命名的参数,将会阻止原生arguments对象的创建。所以勿使用arguments为名称的参数。
  • 胡乱使用this标识符会引起语法错误。
  • 如果多个参数具有相同的命名,那么最后一个参数会优先于先前的,即时这个参数未定义。

Named Function Expressions(函数命名表达式)

你可以通过函数表达式给函数命名,语法上看起来像是函数声明,实则不是。上一段代码:
foo(); // TypeError "foo is not a function" 
bar(); // valid 
baz(); // TypeError "baz is not a function" 
spam(); // ReferenceError "spam is not defined" 
 
var foo = function () {}; // anonymous function expression ('foo' gets hoisted) 
function bar() {}; // function declaration ('bar' and the function body get hoisted) 
var baz = function spam() {}; // named function expression (only 'baz' gets hoisted) 
 
foo(); // valid 
bar(); // valid 
baz(); // valid 
spam(); // ReferenceError "spam is not defined"
												

JavaScript中的作用域与函数和变量声明的提升的更多相关文章

  1. javascript中var let const三种变量声明方式

    javascript中var let const三种变量声明方式 1.var  ①var表示声明了一个变量,并且可以同时初始化该变量. ②使用var语句声明的变量的作用域是当前执行位置的上下文:一个函 ...

  2. Javascript中函数及变量定义的提升

    <html> <head> <title>函数提升</title> <script language="javascript" ...

  3. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  4. [转]Javascript中的自执行函数表达式

    [转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...

  5. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  6. 【翻译】JavaScript中的作用域和声明提前

    原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...

  7. JavaScript中的作用域和闭包

    首先强烈安利<你不知道的JavaScript>,JS初学者进阶必读. 对于从C++.Java等静态语言转向JavaScript的初学者(比如我)来说,JS一些与众不同而又十分要紧的特性使得 ...

  8. JavaScript中的作用域和声明提前

    [翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...

  9. javascript中的立即执行函数(function(){…})()

    javascript中的立即执行函数(function(){…})() 深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包 ...

随机推荐

  1. Java WebService简单使用

    一直在写java但从来没有使用webservice,在网上查了下资料写个简单的使用放这里做备份 具体步骤: 1.新建一个java工程在里面写一个类(服务端)如下: package com.webser ...

  2. java继承和多态

    父类和子类 如果类C1扩展自另一个类C2,那么C1称为子类或派生类,C2称为父类或基类.派生类可以从它的基类中继承可访问的数据域和方法,还可添加新数据域和新方法 例如:实现一个几何图形基类; clas ...

  3. jqgrid使用sql row_number进行分页

    背景 系统中使用了jqgrid的展示,现在要处理10w+的数据量 现状 使用了全查询的,查询到了10w+的数据放到了datatable中,每次页面刷新需要9秒多,并且传递给另一个dll来处理一些事情. ...

  4. CP-ABE环境配置

    本环境配置步骤参考互联网: 1.安装m4 sudo apt-get install m4 2.安装gmphttp://gmplib.org/  下载gmplib ./configure make ma ...

  5. 推荐vpn的文章

    http://wsgzao.github.io/post/fq/ 免费方案 各个平台的解决方案都不唯一,请认真阅读原文中的说明部分 百度浏览器 你这么大摇大摆提供FQ插件,真不用担心360菊(jǔ)爆 ...

  6. linux内存负载分析

    衡量内存负载的一个很重要的指标就是页面置换的频率.当linux系统频繁的对页进行换进换出 的时候,说明物理内存不过,不得不进行频繁的置换页面. 使用vmstat(virtual memory stat ...

  7. cdh4

    libhadoop.so其实是后面安装impala时要用到 此处配置环境变啦时注意 下 export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/l ...

  8. Android实例-使用电话拨号器在移动设备上(官方)(XE8+小米2)

    源文地址: http://docwiki.embarcadero.com/RADStudio/XE5/en/Mobile_Tutorial:_Using_the_Phone_Dialer_on_Mob ...

  9. [C语言 - 14] 进制

    进制 二进制 int number = 0B1010; 没有二进制的输出格式   八进制     int number2 = 07613;     printf("number2 = %o\ ...

  10. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...