读书人

JavaScript:The Good Parts (4)

发布时间: 2012-07-01 13:15:00 作者: rapoo

JavaScript:The Good Parts (四)
第4章 函数(Functions)
4.1函数对象(Function Objects)
4.2函数字面量(Function Literal)
4.3调用(Invocation)
4.4参数(Arguments)
4.5返回(Return)
4.6异常(Exceptions)
4.7给类型增加方法(Augmenting Types)
4.8递归(Recursion)
4.9作用域(Scope)
4.10闭包(Closure)
4.11回调(Callbacks)
4.12模块(module)
4.13
4.14
4.15

JS中最好的特性就是它对函数的实现,它几乎无所不能。
函数包含一组语句,它们是JS的基础模块单元,用于代码复用、信息隐藏和组合调用。
函数用于指定对象的行为。一般来说,所谓编程就是将一组需求分解成一组函数与数据结构的技能。
4.1函数对象(Function Objects)
(1)在JS中函数就是对象。对象是“名/值”对的集合并拥有一个连到原型对象的隐藏连接。对象字面量产生的对象连接到Object.prototype,函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)。每个函数在创建时附有两个附加的属性:函数的上下文和实现函数行为的代码(1.函数的上下文:指的是函数所在的 scope。一个嵌套函数的 scope 是它的外层函数,顶层函数的 scope 是全局。这个 scope 是静态的,不可改变的。一个函数的 scope 一层层向上。http://www.douban.com/group/topic/22693981 2.实现函数行为的代码:JS在创建一个函数对象时,会给该对象设置一个调用属性;当JS调用一个函数时,可以理解为调用此函数的“调用”属性。)。
(2)每个函数对象在创建时也随带有一个prototype属性。它的值是一个拥有constructor属性且值即为该函数的对象(http://blog.csdn.net/adwu73/article/details/7219887)。这和隐藏连接到Function.prototype完全不同。
(3)因为函数是对象,所以它们可以像任何其他的值一样被使用。函数可以存放在变量、对象和数组中。函数可以被当作参数传递给其他函数,函数可以再返回函数。而且因为函数是对象,所以函数可以拥有方法。
(4)函数的与众不同之处在于它们可以被调用。
4.2函数字面量(Function Literal)
函数对象可以通过函数字面量来创建:


通过给基本类型增加方法,可以大大提高语言的表现力。因为JS原型动态本质,新的方法被立刻赋予到所有的值(对象实例)上,哪怕值(对象实例)是在方法被创建之前就创建好了。
4.8递归(Recursion)
(1)递归函数会直接或间接地调用自身的一种函数。递归是一种强大的编程技术,它将一个问题分解为一组相似的子问题,没一个都有一个寻常解去解决。一般来说一个递归函数调用自身去解决它的子问题。
(2)“汉诺塔”问题。
问题描述:塔的设备包括三根柱子和一套直径各不相同的空心圆盘。开始时源柱子上的所有圆盘都按照较小的圆盘放在较大的圆盘之上的顺序堆叠。目标是通过每次移动一个圆盘到另一根柱子,最终将一堆圆盘移动到目标柱子上,过程中不可以将大的圆盘放置在较小的圆盘之上。
问题寻常解:
var serial_maker= function(){    //返回一个用来产生唯一字符串的对象。唯一字符串由2部分组成:前缀+序列号。    //该对象包含一个设置前缀的方法和一个设置序列号的方法,和一个产生唯一字符串的gensym方法    var prefix= '';    var seq= 0;    return {        set_prefix: function(p){            prefix= String(p);        },        set_seq: function(){            seq= s;        },        gensym: function(){            var result= prefix+ seq;            seq+= 1;            return result;        }    };    };var seqer= serial_maker();seqer.set_prefix('Q');seqer.set_seq(1000);var unique= seqer.gensym();  //unique is "Q1000"

seqer包含的方法都没有用到this或that。因此没有办法损害seqer。除非调用对应的方法,否则没办法改变prefix或seq的值。seqer对象是可变的,所以它的方法可能被替换掉,但替换后的方法依然不能访问私有成员。seqer就是一组函数的集合,而且那些函数被授予特权,拥有使用或者修改私有状态的能力。
如果我们把seqer.gensym作为一个值传递给第三方函数,那个函数能用它产生唯一字符串,但却不能通过它来改变prefix和seq的值。

读书人网 >JavaScript

热点推荐