写在前面

看到好多书评和读书笔记都说《JavaScript语言精粹》字字珠玑,名不虚传。。当然,要看得懂才行

其实个人认为函数化部分不是很好,举的例子不是十分恰当,之前看不懂是因为被成功误导了,就像《Head First》设计模式第一章《策略模式》一样,作者有些偏离章节主题,读者容易被误导

声明:姑且把函数化部分给出的用来创建对象的函数称为“创造函数”吧,为了与“构造函数”区分开。。不是很好听,将就着用吧

一.源码中需要注意的点

很容易就能拿到源码,和中文版书上的代码一样,仔细看了一遍发现了一个很精妙的地方,当然,不是很好理解

P.S.源码有点小问题:“创造函数”cat花括号不匹配,中文版54页,return that;之前少了};

Object的原型函数superior内部有一个很精妙的地方

  1. Object.method('superior', function (name) {
  2. var that = this,
  3. method = that[name];
  4. return function ( ) {
  5. return method.apply(that, arguments);
  6. };
  7. });

亮点就是最后一句的arguments,看似无心,其实是有意为之的,表明用superior调用父类方法时也可以传参。当然,传参的话需要修改调用方式,测试代码如下:

  1. Function.prototype.method = function (name, func) {
  2. this.prototype[name] = func;
  3. return this;
  4. };
  5.  
  6. var mammal = function (spec) {
  7. var that = {};
  8.  
  9. that.get_name = function ( ) {
  10. return spec.name;
  11. };
  12.  
  13. that.says = function ( ) {
  14. return spec.saying || '';
  15. };
  16.  
  17. return that;
  18. };
  19.  
  20. var cat = function (spec) {
  21. spec.saying = spec.saying || 'meow';
  22. var that = mammal(spec);
  23. that.purr = function (n) {
  24. var i, s = '';
  25. for (i = 0; i < n; i += 1) {
  26. if (s) {
  27. s += '-';
  28. }
  29. s += 'r';
  30. }
  31. return s;
  32. };
  33. that.get_name = function ( ) {
  34. alert("cat.get_name :" + arguments.length);///
  35. return that.says( ) + ' ' + spec.name +
  36. ' ' + that.says( ) + "[" + arguments.length + "]";
  37. };
  38.  
  39. return that;
  40. };
  41.  
  42. Object.method('superior', function (name) {
  43. var that = this,
  44. method = that[name];
  45. return function ( ) {
  46. alert("superior :" + arguments.length);///
  47. return method.apply(that, arguments);
  48. };
  49. });
  50.  
  51. var coolcat = function (spec) {
  52. var that = cat(spec),
  53. super_get_name = that.superior('get_name');
  54. that.get_name = function () {
  55. alert("coolcat.get_name :" + arguments.length);///
  56. return 'like ' + super_get_name.apply(this, arguments) + ' baby';
  57. };
  58. return that;
  59. };
  60.  
  61. var myCoolCat = coolcat({name: 'Bix'});
  62. var name = myCoolCat.get_name(1, 2, 3);
  63. // 'like meow Bix meow baby'
  64.  
  65. alert(name); // 'like meow Bix meow[3] baby'

P.S.开始以为superior函数最后的arguments是作者的错误,觉得应该需要把外面的arguments对象传给method而不是里面的,绕了一大圈发现是自己错了,道行不够,没能秒懂道格拉斯大爷的意思。。

二.函数化的初衷

函数化部分开篇就说明了初衷:为了实现私有属性,创建最后提到的“防伪对象”

目的无可厚非,实现私有属性太有必要了。但举的例子mammal -> cat -> coolcat太不合适了,作者想说明用函数化的方式可以实现继承

当然,不是严格意义上的继承,因为函数化方式没有用到自定义类型,子类实例与父类实例的is-a关系也就无从谈起了

P.S.看第一遍的时候cat的例子就把我带到沟里去了,以为函数化就是要抛弃new,完全用函数来实现继承。。自然是在沟里越走越深了

三.函数化的思想

直接看代码,代码自己会说话:

  1. /*
  2. * 函数化的思想:
  3. * 1.创建对象
  4. * 2.添加私有属性
  5. * 3.公开接口(添加公有属性)
  6. * 4.返回该对象
  7. */
  8. /*
  9. * method: getSuper
  10. * @param spec 规格说明对象,提供创建对象所需的基本数据
  11. * @param my “创造函数”之间共享数据的容器
  12. */
  13. function getSuper(spec, my){
  14. var obj; // 要返回的对象
  15. var my = my || {}; // 没传入就创建一个
  16.  
  17. // 私有属性
  18. var attr = spec.value; // 从规格说明对象取数据
  19. var fun = function(){
  20. alert(attr);
  21. }
  22.  
  23. // [可选]把需要与其它“创造函数”共享的数据装入my
  24.  
  25. // 创建对象,可以用任意方式,比如new、字面量、调用其它“创造函数”
  26. obj = {
  27. name: "SuperObject"
  28. };
  29.  
  30. // 公开接口
  31. obj.fun1 = fun;
  32.  
  33. // 返回obj
  34. return obj;
  35. }
  36.  
  37. /*
  38. * method: getSub
  39. * 参数同上
  40. */
  41. function getSub(spec, my){
  42. var obj;
  43. var my = my || {};
  44.  
  45. // 私有属性
  46. var attr = spec.value + 1;
  47. var fun = function(){
  48. alert(attr);
  49. }
  50.  
  51. // [可选]共享
  52.  
  53. // 创建对象
  54. obj = getSuper(spec, my); // 可以直接传过去,当然也可以改一改再传,或者传别的什么
  55.  
  56. // 公开接口
  57. obj.fun2 = fun;
  58.  
  59. // 返回obj
  60. return obj;
  61. }
  62.  
  63. // 测试
  64. var spec = {
  65. value: 1
  66. };
  67. var sub = getSub(spec); // 不用传入my,my只应该在“创造函数”之间用
  68. sub.fun1(); // 1
  69. sub.fun2(); // 2

P.S.又是“创建对象 -> 增强 -> 返回新对象”这个套路,不就是尼古拉斯所说的由道格拉斯发明的“模块模式”吗?

四.防伪对象(持久性的对象)

函数化部分的核心就是它了,注意上面例子中公开接口的方式:

  1. // 私有属性
  2. var myFun = function(){/* ... */};
  3. // 公开接口
  4. obj.fun = myFun;

而不直接用:

  1. // 公开接口
  2. obj.fun = function(){/* ... */};

第一种方式更安全,因为即便从外界修改了fun,内部其它调用了myFun的方法仍然可以正常工作,这样的函数对象就是所谓的防伪对象

完整定义:

防伪对象的属性可以被替换或者删除,但该对象的完整性不会受到损害

也被称为持久性的对象,一个持久性对象就是一个简单功能函数的集合

后话

到这里《JavaScript语言精粹》的学习笔记就告一段落了,补好了[函数化]的空缺,学习笔记的其它部分请查看黯羽轻扬:《JavaScript语言精粹》学习笔记

《JavaScript语言精粹》之函数化的更多相关文章

  1. JavaScript中对象与函数的某些事[JavaScript语言精粹-N1]

    今天在读<JavaScript语言精粹>的时候,关于函数的一个部分,始终觉得有点难以理解,代码如下: 1: var obj = (function(){ 2: var value = 0; ...

  2. JavaScript语言精粹 笔记02 函数

    函数函数对象函数字面量调用参数返回异常给类型增加方法递归作用域闭包回调模块级联套用记忆   函数 1 函数对象 在JS中函数就是对象.对象是“名/值”对的集合并拥有一个连接到原型对象的隐藏连接.对象字 ...

  3. 《JavaScript语言精粹》小记

    一.前言 以下内容均摘自<JavaScript语言精粹>一书,本人在读这本书时,发现作者诠释JavaScript很犀利,特别是数组部分,固记录下来,想和大家分享下. 随笔主要包含两大部分: ...

  4. javascript语言精粹

    内容选自:<javascript语言精粹> 1.6种值会为假(==false),分别是false,null,undefined,' ',0,NaN 2.typeof有6种值,分别是'num ...

  5. Javascript 语言精粹 代码片段合集

    Javascript 语言精粹 代码片段合集 标签:Douglas-Crockford Javascript 最佳实践 原文链接 更好的阅读体验 使用一个method 方法定义新方法 Function ...

  6. JavaScript语言精粹笔记

    JavaScript语言精粹笔记 掌握语言的每个特性可以让你出风头,但是并不推荐,因为一部分的特性带来的麻烦可能远超本身的价值.正如书中所言,坏的材料并不能雕刻出好的作品,要成为一名更好的程序员,要取 ...

  7. 《JavaScript语言精粹》学习笔记

    一.in的用法 for...in 枚举一个对象的所有可枚举属性 检测DOM/BOM属性 if ("onclick" in elem) { // 元素支持onclick } if ( ...

  8. 《JavaScript语言精粹》【PDF】下载

    <JavaScript语言精粹>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382204 内容简介 javascript曾是&q ...

  9. JavaScript语言精粹 笔记03 继承

    继承伪类对象说明符原型函数化部件 继承 JS不是基于类的,而是基于原型的,这意味着对象直接从其他对象继承. 1 伪类 JS提供了一套丰富的代码重用模式,它可以模拟那些基于类的模式,因为JS实际上没有类 ...

随机推荐

  1. RAD 版本迁移工具,不怕升级麻烦了。

    RAD 版本迁移工具,不怕升级麻烦了. http://community.embarcadero.com/blogs?view=entry&id=8865 migrationtool.exe ...

  2. Python 之WEB框架

    wsgi模块实现socketPython web框架: - 自己实现socket 代表:Tornado - 基于wsgi(一种规范,统一接口) 代表: Django 自己开发web框架(基于wsgi) ...

  3. JavaScript高级程序设计笔记之面向对象

    说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...

  4. Linux_04------Linux权限的设定

    三种权限 */ /** * 修改文件所有者 * chown 用户名 文件名 */

  5. 一个很酷的加载loading效果--IT蓝豹

    一个很酷的加载loading效果,自定义LeafLoadingView实现,LeafLoadingView继承view, 本例子主要由以下几点构成 (1):RotateAnimation实现叶子旋转 ...

  6. DIOCP之获取在线用户列表

    通过获取tcpserver.getonlinecontextlist来得到在线列表 procedure TfrmMain.btn_refreshClick(Sender: TObject);var l ...

  7. C#WebClient常见用法

    System.Net.WebClient.DownloadFile(Uri address, String fileName) namespace:System.Net 参数: address:The ...

  8. 基于Jquery-ui的自动补全

    1.添加CSS和JS引用 <script type="text/javascript" src="javascript/jquery-1.7.min.js" ...

  9. 团队项目作业:利用NABCD模型进行竞争性需求分析

    NABC正是这样的一套框架,当你试图提出一项崭新的提案之际,它能够提供四个思维基点,令你的商业策划具备天马行空的基础. 具体来说,NABC是四个关键词的首字母缩写- Need(需求)-现在市场上未被满 ...

  10. ue4 SNew补遗

    上一篇分析了SNew背后的实现,但是有一个关键问题遗漏了,那就是: #define SNew( WidgetType, ... ) \ MakeTDecl<WidgetType>( #Wi ...