首先看下面的代码:  

  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. windows版influxDB安装与配置

    一.下载链接https://portal.influxdata.com/downloads,选windows版 二.解压到安装盘,目录如下 三.修改conf文件,代码如下,直接复制粘贴(1.4.2版本 ...

  2. C语言采用socket实现http post方式上传json数据

    1.按照HTTP协议发送请求: http POST 报文格式 http 报文是面向文本的. 报文分为:请求报文和响应报文 请求报文由:请求行,请求头部,空行和请求数据四个部分组成. <1.请求行 ...

  3. csla框架__使用Factory方式实现Csla.BusinessBase对象数据处理

    环境:.net4.6+csla4.6 实现:对象的数据库访问及数据库执行使用Factory方式进行封闭. 正文: 以前在使用csla框架完成业务对象的定义时所有的数据处理都在对象内部实现,也不能说不好 ...

  4. datatable处理gridview筛选后的值

    DataTable dt = (DataTable)gridView1.GridControl.DataSource; DataRow[] drr = dt.Select(gridView1.RowF ...

  5. 安装selenium,驱动geckodriver,及出现的问题

    cmd输入安装selenium指令: pip install selenium 1.报错 Could not find a version that satisfies the requirement ...

  6. spring注解驱动开发

    1.全图: 一.IOC容器部分 1.第一个初始化实例: @Configuration @ComponentScans @Bean("person") 注意: @repeatable ...

  7. dom编程艺术笔记1--第二章

    第二章语法部分: 1.js注释:<!-- XXXXX 而“-->”这部分js会认为是注释内容的一部分 2.var 声明变量 不用声明变量类型 3.声明使用一个数组语法:var object ...

  8. Python的基础语法

    一,编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 当然你也可以为源码文件指定不同的编码: 1 # -*- coding: cp-1252 ...

  9. web前端的前景

    随着时代的发展,现在从事IT方向的人有很多,所以励志要成为前端开发工程师的人有很多.当然也有很多人在犹豫不知道该从事哪个方向,我今天就是来给大家分析一下Web前端开发的前景.包括工作内容,发展前景和薪 ...

  10. mongoDB-Cannot change the size of a document in a capped collection:

    简单记录一下: 造成该问题的原因是集合被设置成了 固定集合 .固定集合的数据不能被修改.只能查找-删除-再插入