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. 魅族MX2代理设置

    魅族MX2买了快2年了,今天才知道有这个功能,唉 连接一个无线网络,比如我的centos 长按网络名字 选代理设置,设置自己的代理,再也不用SS 或 VPN 的android端了,老是提示ROOT权限 ...

  2. 用js将毫秒时间转成正常时间

    1. 将毫秒时间转成正常时间 //#region 将毫秒转换成正常的日期 function getDate(time) { var date = new Date(parseInt(time)); v ...

  3. 从百度API中获取天气

    网络上看到鱼C的Python入门课程不错,语言风格也引人入胜,想做个实验,这东西到底好不好入门, 就把这个视频推荐给老婆,让他试着学一下,做足了老婆的工作. 这不,这两天她很上心,学得很有成就感,我也 ...

  4. Ajax解决缓存的5种方法

    原文:http://www.ido321.com/129.html 1.在ajax发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,”0″ ...

  5. windows安装python开发环境

    1.下载python 官网下载最新版python python-2.7.5.amd64.msi http://vdisk.weibo.com/s/Cd8pPaw56OWbR 2.下载PyCharm 官 ...

  6. 【转载】解析提高PHP执行效率的50个技巧

    1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量, 单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的”函数”(译注:PHP手 ...

  7. 【转载】extern "C"的用法解析(原博主就是抄百度百科的,不如另外一篇好)

    [说明]文章转载自Rollen Holt 的文章 http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html --------- ...

  8. HW5.30

    public class Solution { public static void main(String[] args) { for(int i = 3; i <= 1000; i++) i ...

  9. 问题-关于SizeOf在Delphi7和Delphi2009下结果分别是16/32

    问题:同样的代码在Delphi7和Delphi2009下结果分别是16/32,为什么?var   LWindCode : array [0..15] of char; begin   showmess ...

  10. [iOS基础控件 - 3.5] NSBundle, UIImageView和UIButton的区别, 模拟器和文档

    1.NSBundle1> 一个NSBundle代表一个文件夹,利用NSBundle能访问对应的文件夹2> 利用mainBundle就可以访问软件资源包中的任何资源3> 模拟器应用程序 ...