JavaScript中对象与函数的某些事[JavaScript语言精粹-N1]
今天在读《JavaScript语言精粹》的时候,关于函数的一个部分,始终觉得有点难以理解,代码如下:
1: var obj = (function(){
2: var value = 0;
3:
4: return {
5: increment:function(inc){
6: value += typeof inc == "number"?inc:1;
7: },
8: getValue:function(){
9: return value;
10: }
11: };
12: }());
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
注意代码最后的标黄色的一对括号,书中是这样描述的“我们并没有把一个函数赋值给obj,我们是把调用该函数后返回的结果赋值给它,该函数返回一个包含两个方面的对象,并且这些方法继续享有访问value变量的特权”。其实像这样代码,用的也比较多,只是从来没有仔细琢磨过,如果去掉了最后的一对括号,那么,返回的就是一个函数(对象)了。
如果我们在代码中这样调用上面的obj,则可以直接使用,执行typeof obj 返回结果为”object”,如:
1: obj.increment(1);
2: alert(obj.getValue());//1
3: obj.increment(2);
4: alert(obj.getValue());//3
如果去掉最后的一对括号,执行typeof obj 返回结果为“function”,需要使用先声明初始化的方式,才能使用这个对象,如:
1: var o = obj();
2: o.increment(1);
3: alert(o.getValue());//1
4: o.increment(2);
5: alert(o.getValue());//3
这样似乎理解了有没有那对括号的区别。但是作者后面举的Fibonacci例子,才让我恍然大悟,原来它还有这么个好的用处。即,函数可以将先前的操作结果记录在某个对象里,从而避免无谓的重复运算。
我们通过普通的递归方式,计算Fibonacci数值,代码如下:
1: var totalTimes = 0;
2:
3: var fibonacci = function (n){
4: totalTimes +=1;
5: return n<2?n:fibonacci(n-1) + fibonacci(n-2);
6: }
7:
8: function calculateFibonacci(){
9: totalTimes = 0;
10: for(var i =0;i<11;i++){
11: document.getElementById("rlt").innerHTML +="//"+i+":"+fibonacci(i)+"<br/>";
12: }
13: document.getElementById("rlt").innerHTML+="//totalTimes:"+totalTimes+"<br/>";
14: }
连续执行两次,我们会看到如下的结果:
1: //0:0
2: //1:1
3: //2:1
4: //3:2
5: //4:3
6: //5:5
7: //6:8
8: //7:13
9: //8:21
10: //9:34
11: //10:55
12: //totalTimes:453
13: //0:0
14: //1:1
15: //2:1
16: //3:2
17: //4:3
18: //5:5
19: //6:8
20: //7:13
21: //8:21
22: //9:34
23: //10:55
24: //totalTimes:453
是的,两次都是执行了453次。因为每次都要重新从0,1开始计算。
但是,如果我们使用了如下代码(注意它最后的一对括号):
1: var totalTimes = 0;
2: var fibonacciMemo = function(){
3: var meno = [0,1];
4: var fib = function(n){
5: totalTimes +=1;
6: var result = meno[n];
7: if(typeof result != "number"){
8: result = fib(n-1) + fib(n-2);
9: meno[n] = result;
10: }
11: return result;
12:
13: };
14: return fib;
15: }();
16:
17: function calculateFibonacciEx()
18: {
19: totalTimes = 0;
20: for(var i =0;i<11;i++){
21: document.getElementById("rlt").innerHTML +="//"+i+":"+fibonacciMemo(i)+"<br/>";
22: }
23: document.getElementById("rlt").innerHTML+="//totalTimes:"+totalTimes+"<br/>";
24: }
连续执行两次,我们看到的结果却是这样:
1: //0:0
2: //1:1
3: //2:1
4: //3:2
5: //4:3
6: //5:5
7: //6:8
8: //7:13
9: //8:21
10: //9:34
11: //10:55
12: //totalTimes:29
13: //0:0
14: //1:1
15: //2:1
16: //3:2
17: //4:3
18: //5:5
19: //6:8
20: //7:13
21: //8:21
22: //9:34
23: //10:55
24: //totalTimes:11
是的,第一次执行了29次计算,第二次只执行了11次计算。原因在于我们把结果保存在了meno这个数组中。
当然,我们也可以通过其它方式,如全局变量的形式,将结果保存下来,但是全局变量正是作者极力反对的应用和存储模式之一,而且这个计算结果的保存,本来就是对外透明的,调用它的人需要的只是计算结果,并不需要知道其中如何保存,或者说我们并不需要这个计算函数以外的其它任何(全局)变量,或者任何后来维护这段代码的人,不需要被告知在其它不知道的地方,有计算的中间结果需要他来做多余的维护工作!
当然,我们也可以不用去省掉那400多次计算,不用关心程序的效率,或者不用担心用户的浏览器有多慢!
其实到现在也没有相通,它们之间用处的区别或是优缺点在哪儿,因为始终没想明白说这件事的Point在哪儿,所以,博文的标题总觉得没说清楚哈!希望大家给予指点!
JavaScript中对象与函数的某些事[JavaScript语言精粹-N1]的更多相关文章
- 前端学习 第二弹: JavaScript中的一些函数与对象(1)
前端学习 第二弹: JavaScript中的一些函数与对象(1) 1.apply与call函数 每个函数都包含两个非继承而来的方法:apply()和call(). 他们的用途相同,都是在特定的作用域中 ...
- javascript中对象字面量的理解
javascript中对象字面量与数组字面量 第一部分 我们知道JavaScript中的数据类型有基本数据类型和引用类型,其中Object类型就是非常常用的类型.那么如果创建一个Object类型的实例 ...
- 理解和使用 JavaScript 中的回调函数
理解和使用 JavaScript 中的回调函数 标签: 回调函数指针js 2014-11-25 01:20 11506人阅读 评论(4) 收藏 举报 分类: JavaScript(4) 目录( ...
- 关于JavaScript中对象的继承实现的学习总结
一.原型链 JavaScript 中原型链是实现继承的主要方法.其主要的思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.实现原型链有一种基本模式,其代码如下. function Super ...
- javascript中对象的深度克隆
记录一个常见的面试题,javascript中对象的深度克隆,转载自:http://www.2cto.com/kf/201409/332955.html 今天就聊一下一个常见的笔试.面试题,js中对象的 ...
- [原创]javascript prototype 对象 函数 <精简的美丽......>
精简的美丽...... javascript prototype 对象 函数 在javascript中我们都知道创建一个对象使用如下代码var x = {}对象可以拥有属性和方法var x = { ...
- 在 JavaScript 中使用构造器函数模拟类
今天,我们要讲的是在 JavaScript 中使用构造器函数(construcor function)模拟类. 构造器函数简介 你可以使用 ES6 的 class 关键字来实现类,不过我建议你使用传统 ...
- 来一轮带注释的demo,彻底搞懂javascript中的replace函数
javascript这门语言一直就像一位带着面纱的美女,总是看不清,摸不透,一直专注服务器端,也从来没有特别重视过,直到最近几年,javascript越来越重要,越来越通用.最近和前端走的比较近,借此 ...
- 理解javascript中的回调函数(callback)【转】
在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...
随机推荐
- 20172319 《Java程序设计教程》第7周学习总结
20172319 2018.04.11-16 <Java程序设计教程>第7周学习总结 目录 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题 ...
- Beta阶段冲刺三
Beta阶段冲刺三 Task1:团队TSP 团队任务 预估时间 实际时间 完成日期 新增其他学院的爬虫 180 130 11.30 新增其他学院的数据库字段修改 180 160 12.1 新增其他学院 ...
- Linux学习之CentOS(二)----远程登录管理工具SecureCRT的使用
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...
- win 批处理
前言 批处理文件(batch file)包含一系列 DOS命令,通常用于自动执行重复性任务.用户只需双击批处理文件便可执行任务,而无需重复输入相同指令.编写批处理文件非常简单,但难点在于确保一切按顺序 ...
- 使用fiddler的过滤条件
使用fiddler抓包的时候经常一下子显示很多的记录,看的眼花缭乱,需要这时候需要使用过滤条件来帮助你,一般常用的有三种过滤条件: 1.域名过滤,只显示特定域名的记录: *.baidu.com表示所有 ...
- 小菜菜mysql练习解读分析1——查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数
查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数 好的,第一道题,刚开始做,就栽了个跟头,爽歪歪,至于怎么栽跟头的 ——需要分析题目,查询的是 ...
- Python day5 --------递归、匿名函数、高阶函数、内置函数
一.递归 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归要求: 1. 必须有一个明确的结束条件 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减 ...
- 【BZOJ1005】[HNOI2008]明明的烦恼(prufer序列)
[BZOJ1005][HNOI2008]明明的烦恼(prufer序列) 题面 BZOJ 洛谷 题解 戳这里 #include<iostream> #include<cstdio> ...
- 为什么使用消息队列,为什么使用RabbitMQ、springAMQP
1.为什么使用消息队列? 2.为什么使用RabbbitMQ? 3.为什么使用spring AMQP?
- 在线Python学习网站
目前我们使用的Python集成环境是Anaconda3,然后使用Jupyter Notebook和Spyder两个开发环境 Goole推出了在线的开发环境,在线网站: https://colab.re ...