首先看下面的代码:  

  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. Github 搭建 Hexo 纯静态化个人博客平台

    以前一直想搭建一个属于自己的博客平台,有余种种原因一直未能实现,最近闲来无事,参照网上的教程,搭建了属于自己的博客.自己的博客网站,样式自由,不需要受限于各大平台. 本篇为从零开始的基础篇,本篇所包含 ...

  2. PHP调用Python接口过程中所遇到的问题

    在php调用python脚本时,首先把python相关组件安装完善.用Python命令检测运行脚本而不报错. 在调用接口的过程 1.没有打开的python脚本的权限 解决办法:把python脚本所在的 ...

  3. tomcat中配置ssl的http协议

    问题: IDEA配置tomcat后运行时报如下错误: Error running wis-client-web: SSL HTTP Connector node not found: set up o ...

  4. C语言的#if #ifdef #ifndef

    #if #ifedf #ifndef   —般情况下,C语言源程序中的每一行代码.都要参加编译.但有时候出于对程序代码优化的考虑.希望只对其中一部分内容进行编译.此时就需要在程序中加上条件,让编译器只 ...

  5. Google 最新推出数据集搜索

    继Google在2004年11月推出Google的重量产品Google scholar后,Google在最近推出的另一个重量级产品 Google Dataset Search.众所周知,互联网上的信息 ...

  6. Python序列的一点用法

    #python的基本语法网上已经有很多详细的解释了,写在这里方便自己记忆一些 序列,顾名思义,是一段数据的有序排列,列表,元组,字符串都是序列的一种,序列有很多BIF(BIF是内建方法,即python ...

  7. 分布式大数据系统离线分析技术解决方案(spark2.x)

    一.sark2.x新型的架构系统

  8. Shell bash 数学运算 bc

    1.bc命令可以完成浮点数的运算.其中 scale可以指定保留的小数点位数. 2.举例 例1: 例2:

  9. 2017-9-10"切题如切菜杯"模拟赛T4 ZZI

    题目 YYH拿到了父亲给的钱欣喜若狂,把这些钱拿来造了n栋房子.现在他要给这些房子通电.他有两种方法:第一种是在房间里搭核电发电机发电,对于不同的房子,他需要花不同的代价Vi:,第二种是将有电的房子i ...

  10. json序列化NULL

    在项目中遇到一问题,json序列化需要将null传递给前端,但之前项目中使用的都是fastjson的JSONObject.toJSONString(vo),这样会过滤掉为NULL的属性. 解决办法: ...