《JavaScript语言精粹》之函数化

写在前面

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

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

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

一.源码中需要注意的点

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

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

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

Object.method(‘superior‘, function (name) {
    var that = this,
        method = that[name];
    return function (  ) {
        return method.apply(that, arguments);
    };
});

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

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关系也就无从谈起了

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语言精粹》学习笔记

时间: 2024-08-26 21:27:37

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

《JavaScript语言精粹》—— 函数篇

三.函数 (1) 函数对象 在JavaScript中,函数就是对象.对象字面量产生的对象连接到Object.prototype.函数对象连接到Function.prototype(但其实该对象原型也是连接到Object.prototype).每个函数在创建时会附加两个隐藏属性:函数的上下文和实现函数行为的代码(在JavaScript创建一个函数对象时,会给对象设置一个"调用属性"). 每个函数对象在创建时也会配送一个prototype属性.它的值是一个拥有constructor属性且值

《javascript语言精粹》——第4章函数

函数就是对象 [1].函数字面量即(函数表达式)包括四部分: 第一部分:保留字function: 第二部分:函数名称,可有可无: 第三部分:包围在一对小括号的一组参数,参数用逗号隔开: 第四部分:包围在一对花括号的一组语句,是函数的主体: 函数字面量可以出现在任何允许表达式出现的地方. [2].调用有四种调用模式: 除了声明时定义的形参,每个函数接收附加的的参数:this和arguments  ,this的值取决于调用的模式. 第一种:方法调用模式: var aa={ value:0, incr

《Javascript语言精粹》的学习(一).对象和函数

最近在学习小马和秦歌翻译的<javascript语言精粹>,果然如传闻般,里面的内容博大精深.有些章节所表达的意思往往需要看到后面的章节内容时才能够突然顿悟,因此,称这本书需要反复的去研究,真的名副其实.这两天看了对象和函数这两章,在这里把自己觉得需要关注的内容做一下笔记: ①对象常量中属性名的命名规范 记得刚开始学习对象常量的时候,觉得它真的很简便.一个对象名,一个大括号,N个“名/值”对,OK,搞定!可是在学习的过程中,也遇到过一些疑惑,比如在一些JS书籍中,在写对象常量时,对象中有的属性

JavaScript语言精粹 笔记01

内容比较简单,只是从头梳理一下JS的知识 语法空白标识符数字字符串语句 对象对象字面量检索更新引用原型反射枚举删除减少全局变量污染  语法 1 空白 空白可能表现为格式化字符或注释的形式.空白通常没有意义,但是偶尔必须用它来分割字符序列,否则它们就会被合并成一个单一的符号.例如: var that = this; var 和that之间的空格是不能去掉的,其他的空格都可以被移除. JS提供两种注释: /* */ // 建议使用//,因为/* */中要注释的内容可能包括字符 */ 而报错,例如:

javascript语言精粹----笔记【转载】

javascript语言精粹----笔记 1.6种值会为假(==false),分别是false,null,undefined,' ',0,NaN 2.typeof有6种值,分别是'number','string','boolean','undefined','function','object';其中typeof(null),结果是'object' 3.number类型总是64位浮点数,两个整数相除也可能出现非整数结果 4.如果第一个运算数的值为假,那么运算符&&产生它的第一个运算数的值.

JavaScript语言精粹 笔记03

继承伪类对象说明符原型函数化部件 继承 JS不是基于类的,而是基于原型的,这意味着对象直接从其他对象继承. 1 伪类 JS提供了一套丰富的代码重用模式,它可以模拟那些基于类的模式,因为JS实际上没有类,所以把模拟的类称为伪类.我们可以定义一个构造器并扩充它的原型: var Mammal = function (name) { this.name = name; }; Mammal.prototype.get_name = function ( ) { return this.name; }; M

JavaScript语言精粹读书笔记- JavaScript对象

JavaScript 对象 除了数字.字符串.布尔值.null.undefined(都不可变)这5种简单类型,其他都是对象. JavaScript中的对象是可变的键控集合(keyed collections). 对象是属性的容器,其中每个属性都拥有名字和值. JavaScript中的对象是无类别的(class-free)的.它对新属性的名字和值没有约束. JavaScript包括一个原型链特性,允许对象继承另一对象的属性. 对象的检索: stooge[“first-name”]或者stooge.

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

<JavaScript语言精粹>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382204 内容简介 javascript曾是"世界上最被误解的语言",因为它担负太多的特性,包括糟糕的交互和失败的设计,但随着ajax的到来,javascript"从最受误解的编程语言演变为最流行的语言",这除了幸运之外,也证明了它其实是一门优秀的语言.douglascrockford在本书中剥开了javascrip

JavaScript语言精粹笔记

JavaScript语言精粹笔记 掌握语言的每个特性可以让你出风头,但是并不推荐,因为一部分的特性带来的麻烦可能远超本身的价值.正如书中所言,坏的材料并不能雕刻出好的作品,要成为一名更好的程序员,要取其精华去其糟粕.当你知道要做什么的时候,它还能表现的更好,编程时一件相对困难的事情,绝不应该在懵懂的状态下开始编程之旅. JS中的注意为//或者/*content*/,注释一定要精确地描述代码,不然没有用的注释比没有注释更糟糕. JS中的代码块不会创建新的作用域,因此变量应该被定义在函数的头部,而不