首先看下面的代码:  

  var x = 1       
  var f1 = function( f ) {
  var x = 2 ;
  f( ' console.log( x ) ' )
  }
  var f2 =  function( ) {
  var x = 2 ;
  eval( ' console.log( x ) ' )
  }
  f1( eval )  // 1
  f2( )  // 2
  
  eval 是一个 global 对象的内置函数,即便在 window 对象内,它也可以作为全局函数使用。
  如果你对结果有疑问,那为了搞懂原因,需要了解 JavaScript 一个重要的知识点: 作用域 ,上下文环境
  
  很多书籍和大牛都会引用 上下文环境 这一概念,在我看来,上下文环境只是一种更加繁琐的理解方式,甚至可以说是完全多余,如果去函数内寻找对应的属性,只会发现一个包含scope关键字的属性与作用域对应,在我看来,上下文环境只是一个被人为创造的词汇,是为了便于他人理解而创建出来的抽象概念。
 
  如果你接受了我上面的观点,那作用域就同时囊括了上下文环境的特性,以下两个观点是理解作用域的关键:
 
  第一,只有在函数执行的时候作用域才会生成,函数体内代码未被执行的情况作用域是不会生效的;
  第二,函数体所在处才是代码执行的地方,依据第一个观点,也即作用域生成的地方,是以此寻找上级作用域的起点。
 
  和其他强类型语言不同,JavaScript 能创造独立作用域的方式还不够丰富,函数声明就是其中之一,在不考虑闭包等其他操作联通作用域的情况下,同级作用域之间是绝对屏蔽的,即便是嵌套的作用域,也只允许子作用域向上查询,父级作用域无法向下进入子作用域。
 
  需要注意的是,不是子作用域的所有变量都可以向上去查询,比如 this ,作为一门极其灵活而又混沌的语言,js不会允许这种情况发生,于是ES6这一标准提出了箭头函数的概念,其作用是为 this 开辟一条通向上级作用域的特快通道,将 this 发射出去,这在本质上使得 JavaScript 的逻辑变得更加灵活了,不像其他语言具有较强的模式化属性。
 
  有点脱离主题了,说回为什么两者的输出结果不一致,引用函数其实也是一个包装过的概念,比如本例中的 f ,它的本质只是栈内存的索引地址,更重要的是这一地址指向的并不是存储在堆内存里的函数对象,而是指向另一个栈内存内的地址 eval ,eval 才是真正指向函数的指针,也可以直接将其理解为 eval 函数在栈内存内的唯一代言,毫无疑问,函数体内部才存在作用域,作用域的本质不过是附着了很多变量属性的对象,需要注意的是,此例中并不是指 f1 和 f2 这两个函数对象,而是指其引向的函数体 { } 这个对象。
 
  如果你真正理解了上面我这段话,那么也就不难理解结果不同的原因,f( 'console.log( x ) ' )在执行的时候实际上还是去寻找 eval 所指向的作用域,而 eval 的上级作用域是全局作用域,其作用域内 x 的值是为 1 。
 
  
 

JavaScript中函数引用调用和函数直接调用的区别的更多相关文章

  1. 一篇文章把你带入到JavaScript中的闭包与高级函数

    在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. funct ...

  2. JavaScript中常见的数组操作函数及用法

    JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...

  3. JavaScript中常见的字符串操作函数及用法

    JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...

  4. JavaScript中变量声明有var和没var的区别

    JavaScript中变量声明有var和没var的区别 JavaScript中有var和没var的区别 Js中的变量声明的作用域是以函数为单位,所以我们经常见到避免全局变量污染的方法是 (functi ...

  5. 【转载】在Javascript中 声明时用"var"与不用"var"的区别

    原文链接:http://www.2cto.com/kf/201204/128406.html[侵删]   Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有 ...

  6. 在Javascript中 声明时用"var"与不用"var"的区别,== 和 ===的区别

    今天,被问到两个JS问题,当时没回答到重点,问题虽然看起来简单,但是细节却马虎不得,在此做下记录: 1. 在Javascript中 声明时用"var"与不用"var&qu ...

  7. JavaScript中的闭包和匿名函数

    JavaScript中的匿名函数及函数的闭包   1.匿名函数 2.闭包 3.举例 4.注意 1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没 ...

  8. JavaScript中的闭包与匿名函数

    知识内容: 1.预备知识 - 函数表达式 2.匿名函数 3.闭包 一.函数表达式 1.定义函数的两种方式 函数声明: 1 function func(arg0, arg1, arg2){ 2 // 函 ...

  9. 谈谈javascript中的变量提升还有函数提升

    在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...

  10. javascript中的两个定时函数setTimeOut()和setInterVal()的区别

    js中经常性要用到间隔几秒或暂停几秒执行某个函数, 简单介绍我从网上收集到setTimeOut()和setInterVal()的区别1.setInterVal()介绍 1)定义 setInterval ...

随机推荐

  1. js实现农历时间代码

    var dNow = new Date(); var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲 ...

  2. Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  3. docker 下安装gitlab

    1.找到docker镜像 docker search gitlab 2.下载gitlab镜像 docker pull  gitlab/gitlab-ce/ 3.通常会将 GitLab 的配置 (etc ...

  4. input输入框失去焦点,软键盘关闭后,滚动的页面无法恢复到原来位置

    H5微信页面开发,软键盘弹起后,若原输入框被遮挡,页面整体将会上移,然而当输入框失焦,软键盘收起后,页面未恢复,导致弹框里的按钮响应区域错位. 解决方案:给输入框(或select选择框)添加失去焦点的 ...

  5. 浅析HashMap的实现原理

    本文参照https://www.cnblogs.com/chengxiao/p/6059914.html#commentform作者的文章,并分享一些自己的体会. 本文将主要回答以下两个问题: 1. ...

  6. C++中_T的用途

    1    C++语言中“_T”是什么意思? Visual C++里边定义字符串的时候,用_T来保证兼容性,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到uni ...

  7. php留言板程序

    =================== 先创建note.php <html><head><title>PHP留言本</title></head&g ...

  8. CentOS7.4+OpenStack-Queens版本部署

    一.准备工作.网络选择NAT 创建两台虚拟机:linux-node1.linux-node2 node1: 修改主机名 [root@localhost ~]# hostnamectl set-host ...

  9. codeforces 1140D(区间dp/思维题)

    D. Minimum Triangulation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  10. 自己练习的一个小的demo的时候a标签关于href链接的问题

    一.Js的几种调用方法(参考总结的) 1.a href="javascript:js_method();" 这是常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且 ...