《JavaScript高级程序设计》第7章 函数表达式
定义函数的方式有两种:函数声明和函数表达式
// 函数声明
function function_name(argument) {
// body...
} // 函数表达式
var function_name = function (argument) {
// body...
}
由于函数声明提升,在执行之前会先读取函数声明,所以调用的语句可以放在函数声明之前。但是函数表达式则不可以把调用的语句放在之前。
sayHi(); // 不会报错
function sayHi() {
console.log("Hi!");
} sayHi(); // 错误:函数不存在
var sayHi = function () {
console.log("Hi!");
}
7.1 递归
arguments.callee是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用。
function factorial(num) {
  if (num <= 1) {
    return 1;
  } else {
    // arguments.callee是一个指向正在执行的函数的指针
    return num * arguments.callee(num - 1);
  }
}
在编写递归函数时,使用arguments.callee总比使用函数名更保险(避免函数名突然被赋成null之类的导致出错)
但在严格模式下不可以访问arguments.callee,可以使用命名函数表达式来达成同样的效果。
var factorial = (function f(num) {
  if (num <= 1) {
    return 1;
  } else {
    return num * f(num - 1);
  }
});
7.2 闭包
闭包是一个函数,这个函数可以访问另一个函数作用域中的变量。
function createComparison(propertyName) {
  return function (object1, object2) {
    // 以下两行代码访问了外部函数中的变量propertyName
    // 即使这个函数被返回了,而且在其他地方被调用了,它仍然可以访问变量propertyName
    var value1 = object1[propertyName];
    var value2 = object2[propertyName];
    if (value1 < value2) {
      return -1;
    } else if (value1 > value2) {
      return 1;
    } else {
      return 0;
    }
  };
}
上面的例子中,propertyName是在createComparison函数的作用域中,但里面的匿名函数被返回了之后,就算在其他地方被调用,也能访问到propertyName。
我的理解:通常的函数在执行完毕之后,其局部活动对象(包括arguments和局部变量)就会被销毁。但是如果一个函数体内有闭包的话(也就是它里面有另一个函数,这个函数引用了它的局部活动对象),则在这个函数执行完毕之后,其局部活动对象也不会被销毁,因为它体内的闭包的作用域链仍然在引用这个活动对象。

7.2.1 闭包和变量
function createFunctions() {
  var result = new Array();
  for (var i = 0; i < 10; i++) {
    result[i] = function () {
      return i;
    }
  }
  return result;
}
var iFun = createFunctions();
console.log(iFun[0]());
// 当我调用iFun的时候,createFunctions早就执行完毕了,这时候i的值为10,而由于闭包的缘故i没有被销毁
// 所以实际上iFun数组的所有函数引用的i都是同一个i,值都为10
function createFunctions() {
  var result = new Array();
  for (var i = 0; i < 10; i++) {
    result[i] = function(num) {  // B
      return function() {
        return num;  // A
      }
    }(i);
  }
  return result;
}
var iFun = createFunctions();
console.log(iFun[0]());
// 这个与上一个函数的不同之处在于,当我调用iFun的时候,进的是A位置
// 就算是那个有num参数的匿名函数(B位置)已经执行完了,它的num保存的值没有变过,还是当时传进去的索引i
// 对于iFun数组的每一个函数,他们的外层B都是不同的(num不同),就能达成目的
7.2.2 关于this对象
this问题丢失的实质:闭包通常在另一个作用域中被调用,并且它有自己的this(通常来说是window,因为闭包被调用的作用域通常是全局作用域),会屏蔽掉外层作用域的this(比如说以下例子中的object)。
var object = {
  name: "My Object",
  getNameFunc: function() { // B
    return function() {
      return this.name;  // 调用的时候已经在全局作用域下,屏蔽掉了B位置作用域的this(也就是object)
    }
  };
}
console.log(object.getNameFunc()()); // "The Window"
而that模式能修复这个问题的原因:因为闭包中没有自己的that呀,所以它只能往上找,找到外层作用域中的that了。
7.4 私有变量
任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。
但是通过闭包,我们可以创建用于访问私有变量的公有方法,这种公有方法叫做特权方法。
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:DIYgod
链接:https://www.anotherhome.net/2073
来源:Anotherhome function MyObject() {
// 私有变量和私有函数,外部无法访问
var privateVariable = 'DIYgod';
function privateFunction() {
console.log('lalala');
}
// 特权方法
this.publicMethod = function () {
console.log(privateVariable);
privateFunction();
};
}
var o = new MyObject();
o.publicMethod(); // DIYgod lalala
o.privateFunction(); // Uncaught TypeError: o.privateFunction is not a function
《JavaScript高级程序设计》第7章 函数表达式的更多相关文章
- 《JavaScript高级程序设计》笔记:函数表达式(七)
		
递归 function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } ...
 - 《JavaScript》高级程序设计第7章 函数表达式
		
7.2 闭包 定义: 闭包是指有权访问另一个函数作用域中的变量的函数. 理解闭包: 作用域链: 当某个函数被调用时,会创建一个执行环境以及相应的作用域链. 作用域链中,外部函数的活动对象始终处于第二位 ...
 - 读书笔记 - js高级程序设计 - 第七章 函数表达式
		
闭包 有权访问另一个函数作用域中的变量的函数 匿名函数 函数没有名字 少用闭包 由于闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存.过度使用闭包可能会导致内存占用过多,我们建议读者 ...
 - 《JavaScript高级程序设计》——第二章在HTML使用JavaScript
		
这章讲的是JavaScript在HTML中的使用,也就是<script>元素的属性.书中详细讲了async.defer.src和type四个<script>的属性. 下面是对第 ...
 - js高级程序设计(七)函数表达式
		
定义函数的方式有两种:一种是函数声明,另一种就是函数表达式.函数声明的语法是这样的. function functionName(arg0, arg1, arg2) { //函数体 } Firefox ...
 - JavaScript 高级程序设计 第5章引用类型 笔记
		
第五章 引用类型 一.object类型 1.创建方法: 1.使用new 操作符创建 var person=new object() Person.name=”Nicholasa” Porson.age ...
 - 读书时间《JavaScript高级程序设计》三:函数,闭包,作用域
		
上一次看了第6章,面向对象.这里接着看第7章. 第7章:函数表达式 定义函数有两种方式:函数声明.函数表达式 //函数声明 function functionName(arg0,arg1,arg2){ ...
 - JAVASCRIPT高程笔记-------第 七章   函数表达式
		
7.1递归 经典递归例子 function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - ...
 - JavaScript高级程序设计第20章JSON 笔记 (学习笔记)
		
第二十章 JSON 1.Json 可以表示三种类型的值: 1.简单值: 表示数值:5 表示字符串:“hello wrold”注表示字符串时必须使用双引号 2.对象: {“name”:“mi”,”ag ...
 - JavaScript高级程序设计第14章表单脚本 (学习笔记)
		
第十四章 表单脚本 1.阻止默认表单提交 1.提交表单数据 1.使用type=submit提交按钮 2.使用submit():方法 注意:当用户点击提交按钮时,会触发submit事件,从而在这里我们有 ...
 
随机推荐
- mysql crete view
			
CREATE VIEW user_algo_view ASselect `u`.`userId` AS `UserId`,`u`.`userCode` AS `UserCode`,group_conc ...
 - Android Activity 生成及Activity之间传值
			
Activity 是Android中重要的组件,每个Activity对应一个界面,如何生成新的Activity,如何在不同Activity传递数值呢. 一. 生成新的Activity,当然要使用Int ...
 - 页面的日志服务 web页面渲染 服务  ;  服务耦合带来的问题
			
情景: 虽然对web服务做了3节点的负载均衡,但是由于埋点数据的落盘的代码也在相同服务器上,导致当flume处理日志的吞吐量达到瓶颈时,3节点的请求积压,挤占服务器资源,导致接口数据处理迟缓,页面加载 ...
 - Apache Lucene评分机制的内部工作原理
			
Apache Lucene评分机制的内部工作原理' 第5章
 - Linux内核协议栈相关资料链接
			
1.Linux内核网络分析(个人博客集合,分析较清晰) http://blog.csdn.net/qy532846454/article/category/1385933/2
 - Python高级教程-返回函数
			
函数作为返回值 高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回. 要实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = 0 ...
 - Spring的IoC模式
			
1.依赖 依赖就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖.如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它.下面看一个 ...
 - jvm堆配置参数
			
1.-Xms初始堆大小默认物理内存的1/64(<1GB)(官方建议)2.-Xmx最大堆大小默认物理内存的1/4(<1GB)(官方建议),实际中建议不大于4GB3.一般建议设置 -Xms=- ...
 - windows8系统安装MongoDB 2.6.3配置服务启动
			
转自:http://winfan.net/655.html 1. 下载mongodb包2. 解压zip至 D:\MongoDB3. 创建目录 D:\MongoDB\data\db4. 创建日志目录 D ...
 - oracle procedure简单的将临时表的数据插入或更新到目标表
			
CREATE OR REPLACE PROCEDURE DEAL_SYNC_SCH_CUSTPHONE_NEW AS CURSOR C_CURU IS SELECT * FROM CBS_COS.SC ...