看到好多书评和读书笔记都说《JavaScript语言精粹》字字珠玑,名不虚传。。固然,要看得懂才行javascript
其实我的认为函数化部分不是很好,举的例子不是十分恰当,以前看不懂是由于被成功误导了,就像《Head First》设计模式第一章《策略模式》同样,做者有些偏离章节主题,读者容易被误导html
声明:姑且把函数化部分给出的用来建立对象的函数称为“创造函数”吧,为了与“构造函数”区分开。。不是很好听,将就着用吧java
很容易就能拿到源码,和中文版书上的代码同样,仔细看了一遍发现了一个很精妙的地方,固然,不是很好理解设计模式
P.S.源码有点小问题:“创造函数”cat花括号不匹配,中文版54页,return that;
以前少了};
安全
Object.method('superior', function (name) { var that = this, method = that[name]; return function ( ) { return method.apply(that, arguments); }; });
亮点就是最后一句的arguments,看似无意,实际上是有意为之的,代表用superior调用父类方法时也能够传参。固然,传参的话须要修改调用方式,测试代码以下:app
Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; }; var mammal = function (spec) { var that = {}; that.get_name = function ( ) { return spec.name; }; that.says = function ( ) { return spec.saying || ''; }; return that; }; var cat = function (spec) { spec.saying = spec.saying || 'meow'; var that = mammal(spec); that.purr = function (n) { var i, s = ''; for (i = 0; i < n; i += 1) { if (s) { s += '-'; } s += 'r'; } return s; }; that.get_name = function ( ) { alert("cat.get_name :" + arguments.length);/// return that.says( ) + ' ' + spec.name + ' ' + that.says( ) + "[" + arguments.length + "]"; }; return that; }; Object.method('superior', function (name) { var that = this, method = that[name]; return function ( ) { alert("superior :" + arguments.length);/// return method.apply(that, arguments); }; }); var coolcat = function (spec) { var that = cat(spec), super_get_name = that.superior('get_name'); that.get_name = function () { alert("coolcat.get_name :" + arguments.length);/// return 'like ' + super_get_name.apply(this, arguments) + ' baby'; }; return that; }; var myCoolCat = coolcat({name: 'Bix'}); var name = myCoolCat.get_name(1, 2, 3); // 'like meow Bix meow baby' alert(name); // 'like meow Bix meow[3] baby'
P.S.开始觉得superior函数最后的arguments是做者的错误,以为应该须要把外面的arguments对象传给method而不是里面的,绕了一大圈发现是本身错了,道行不够,没能秒懂道格拉斯大爷的意思。。函数
函数化部分开篇就说明了初衷:为了实现私有属性,建立最后提到的“防伪对象”学习
目的无可厚非,实现私有属性太有必要了。但举的例子mammal -> cat -> coolcat太不合适了,做者想说明用函数化的方式能够实现继承测试
固然,不是严格意义上的继承,由于函数化方式没有用到自定义类型,子类实例与父类实例的is-a关系也就无从谈起了this
P.S.看第一遍的时候cat的例子就把我带到沟里去了,觉得函数化就是要抛弃new,彻底用函数来实现继承。。天然是在沟里越走越深了
直接看代码,代码本身会说话:
/* * 函数化的思想: * 1.建立对象 * 2.添加私有属性 * 3.公开接口(添加公有属性) * 4.返回该对象 */ /* * method: getSuper * @param spec 规格说明对象,提供建立对象所需的基本数据 * @param my “创造函数”之间共享数据的容器 */ function getSuper(spec, my){ var obj; // 要返回的对象 var my = my || {}; // 没传入就建立一个 // 私有属性 var attr = spec.value; // 从规格说明对象取数据 var fun = function(){ alert(attr); } // [可选]把须要与其它“创造函数”共享的数据装入my // 建立对象,能够用任意方式,好比new、字面量、调用其它“创造函数” obj = { name: "SuperObject" }; // 公开接口 obj.fun1 = fun; // 返回obj return obj; } /* * method: getSub * 参数同上 */ function getSub(spec, my){ var obj; var my = my || {}; // 私有属性 var attr = spec.value + 1; var fun = function(){ alert(attr); } // [可选]共享 // 建立对象 obj = getSuper(spec, my); // 能够直接传过去,固然也能够改一改再传,或者传别的什么 // 公开接口 obj.fun2 = fun; // 返回obj return obj; } // 测试 var spec = { value: 1 }; var sub = getSub(spec); // 不用传入my,my只应该在“创造函数”之间用 sub.fun1(); // 1 sub.fun2(); // 2
P.S.又是“建立对象 -> 加强 -> 返回新对象”这个套路,不就是尼古拉斯所说的由道格拉斯发明的“模块模式”吗?
函数化部分的核心就是它了,注意上面例子中公开接口的方式:
// 私有属性 var myFun = function(){/* ... */}; // 公开接口 obj.fun = myFun;
而不直接用:
// 公开接口 obj.fun = function(){/* ... */};
第一种方式更安全,由于即使从外界修改了fun,内部其它调用了myFun的方法仍然能够正常工做,这样的函数对象就是所谓的防伪对象了
完整定义:
防伪对象的属性能够被替换或者删除,但该对象的完整性不会受到损害
也被称为持久性的对象,一个持久性对象就是一个简单功能函数的集合
到这里《JavaScript语言精粹》的学习笔记就告一段落了,补好了[函数化]的空缺,学习笔记的其它部分请查看黯羽轻扬:《JavaScript语言精粹》学习笔记