首先看下面的代码:  

  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. 【原创】KMP算法代码(C)

    //s是模式字符串,t是匹配字符串(可以看我上一篇文章中的叙述) int KMP(const char * s , const char * t) { int slen = strlen(s) , t ...

  2. 9ci

  3. LCT模板(无讲解)

    怎么说呢,照着打一遍就自然理解了,再打一遍就会背了,再打一遍就会推了. // luogu-judger-enable-o2 #include<bits/stdc++.h> using na ...

  4. 三大统计相关系数:Pearson、Spearman秩相关系数、kendall等级相关系数

    统计相关系数简介 由于使用的统计相关系数比较频繁,所以这里就利用几篇文章简单介绍一下这些系数. 相关系数:考察两个事物(在数据里我们称之为变量)之间的相关程度. 如果有两个变量:X.Y,最终计算出的相 ...

  5. h5或者微信端吊起app

    [https://www.cnblogs.com/shadajin/p/5724117.html]! 魔窗sdk http://www.magicwindow.cn/doc/universal-lin ...

  6. SQL-58 获取有奖金的员工相关信息。

    题目描述 获取有奖金的员工相关信息.CREATE TABLE `employees` (`emp_no` int(11) NOT NULL,`birth_date` date NOT NULL,`fi ...

  7. static(静态)关键字

    class Person{String name; //成员变量,实例变量(实例中的变量) //共享数据出现在对象之前static String country="cn"; //对 ...

  8. cdh集群认证命令

    1.集群认证命令 kinit -kt csliyb.keytab csliyb 2.查看认证有效期命令 klist命令 3.延长认证有效期命令 kinit -R 4.手动认证失效命令 kdestroy

  9. Spring源码学习(5)—— bean的加载 part 2

    之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了.这里着重看单例的bean的加载 if(ex1.isSingleton()) { sharedIns ...

  10. 以编程方式使用 Microsoft Office Visio 2003 ActiveX 控件

    以编程方式使用 Microsoft Office Visio 2003 ActiveX 控件 2007/10/29 Mark BukovecEmpire Down Development 适用于:Mi ...