YUI学习笔记(2)

by xujiwei (http://www.xujiwei.com/)

YAHOO.lang.dump 与 YAHOO.lang.substitute。

1. YAHOO.lang.dump(yahoo.js)

dump 方法用来将一个对象转储为一个字符串,并且可以指定转储的深度。

在 dump 过程中,对于基础类型例如 Number、String、Boolean,是直接返回字符串的,对 HTMLElement 对象是返回 HTMLElement 本身,也就是不做处理,对于函数 Function 则是返回字符串“f(){...}”。

对于数组,dump 返回的格式就如我们定义时一样“[item1, item2 item3, ...]”,对于对象 Object,则是使用键值对的形式“key => value”,与 PHP 里面的数组定义方式相似。

例如一个对象定义如下:

var obj = {
num: 1,
str: "string",
bool: true,
date: new Date(),
obj: {
obj_num: 1,
obj_str: "obj_string"
},
foo: function() {
}
}

    dump 之后的字符串如下:

    {num => 1, str => string, bool => true, date => Wed Jan 7 15:57:52 UTC+0800 2009,obj => {obj_num => 1, obj_str => obj_string}, foo => f(){...}}

    字符串没有被引号引起来,这个方法只适合用来展示对象的结构,与 JSON 序列化差得有点远了。

    2. YAHOO.lang.substitute(yahoo.js)

    substitute 实现的功能与 C# 中的 String.Format 方法类似,用来格式化一个字符串,但是它是一个字符串来代表一个占位符,而不像 C# 中是使用数字,或许这个用法和 python 中的字符串格式化更像。

    substitute 调用的格式为:substitute(formatString, valueObject [,formatCallback]),其中 formatString 是作为格式化字符串的字符串,其中包含着一些格式为 {key} 这样的占位符,valueObject 是包含要取代占位符的值的对象,它的结构为 { key1 : value1, key2 : value2 },最后的 formatCallback 参数则是额外的格式化处理函数,用来在格式化字符串进行一些额外的处理。

    substitute 格式化字符串的占位符格式为“{key [meta]}",其中 meta 是可选的,用来表示额外的格式化属性,而要替换的数据则是 valueObject 中名称为占位符 key 的属性,例如,使用 { name : "xujiwei" } 做为数据,那么“{name}”将被替换为“xujiwei”。

    基本数据类型例如 String、Number 在 substitute 中是直接替换的,但是如果要替换的值为一个数组,那么 subtitute 会先使用 YAHOO.lang.dump 方法将对象转储为一个字符串再进行替换,深度为 10,而在替换的值为一个对象时,则会先检测 meta 数据中是否包含了 dump 关键字,或者这个对象的 toString 方法是否与 Object 对象原型的 toString 方法一样,如果是的话就使用 YAHOO.lang.dump 方法来将对象转储为字符串进行替换,否则就调用对象的 toString 方法得到字符串进行格式化。

    如果替换的数据类型不是 Object、Array、String、Number 中的一种的话,那么这个占位符就不进行替换。

    一个覆盖了所有类型数据的例子如下:

    YAHOO.lang.substitute(
    "String : {key1}\nNumber : {key2}\nObject : {key3}\nArray : {key4}",
    {
    key1 : "xujiwei",       // String
    key2 : 123456,          // Number
    key3 : {
    firstName : "Jiwei",
    lastName  : "Xu"
    },                      // Object
    key4 : [1, 2, 3]        // Array
    });

      它的输出如下:

      String : xujiwei

      Number : 123456

      Object : {firstName => Jiwei, lastName => Xu}

      Array : [1, 2, 3]

      对于不支持的类型,substitute 则会在先将占位符替换成 ~-id-~ 的格式,将占位符保存,在进行完所有占位符的处理后再使用正则表达式将 ~-id-~ 替换成原来的占位符。

      substitute 没有对 Boolean 类型的数据进行处理,所以如果要替换的数据为 Boolean 时,那么就不能正确格式化字符串了,不知道为什么 YUI 的开发工程师为什么没有去处理 Boolean 类型的数据。而对于 Function 类型的数据,不加 meta 的情况则是直接替换成了 Function 的定义字符串,这是因为 Function 的 toString 方法与 Object 原型的 toString 不一样,但是又没有 meta 指定格式化方式为 dump。

      占位符中还可以使用 meta 来附加一个额外的格式化属性,例如在替换的值为对象时可以指定转储的深度,又或者值为 Function 时指定格式化方法为 dump 而不是使用 Function 的定义字符串来进行替换。预定义中可以使用的 meta 只有 dump 一个,表示使用 YAHOO.lang.dump 方法将对象或函数转换成字符串,并且 dump 后可以跟一个数字表示转储的深度,例如:

      YAHOO.lang.substitute(
      "Function without dump : {key1}\nFunction with dump : {key1 dump}\nObject without dump0 : {key2}\nObject with dump0 : {key2 dump0}",
      {
      key1 : function() { return 'key1'; },
      key2 : {
      name : {
      firstName : "Jiwei",
      lastName  : "Xu"
      }
      }
      });

        Function without dump : function() { return 'key1'; }

        Function with dump : f(){...}

        Object without dump0 : {name => {firstName => Jiwei, lastName => Xu}}

        Object with dump0 : {name => {...}}

        没有 dump 时,key1 直接被替换成“function() { return 'key1'; }”,而附加了 dump 后,key1 被替换成“f(){...}”。没有指定 dump 的深度时,key2 被替换成完整的对象结构“{name => {firstName => Jiwei, lastName => Xu}}”,指定了 dump 深度为 0 时,key2 的 name 属性被转换为字符串“name => {...}”,而不是它的完整结构。

        substitute 的第三个参数可以指定一个回调函数,在格式化的过程中进行一些自定义的处理,例如我们可以使用这个参数来把 Boolean 类型给格式化成字符串,而不是不能替换。回调函数的格式为 callback(key, value, meta),为了进一步增强 Boolean 的格式化功能,我们可以定义格式化 Boolean 数据时的 meta 为 number 或 string,即 Boolean 值可以转换成 1 或 0,true 或false。

        YAHOO.lang.substitute(
        "Boolean : {key1}\nBoolean in number : {key1 number}\nBoolean in string : {key1 string}", { key1 : true },
        function(key, value, meta) {
        if (typeof value == "boolean") {
        meta = meta || "string";
        if (meta == "string") {
        value = value === true ? "true" : "false";
        }
        else if (meta == "number") {
        value = value === true ? "1" : "0";
        }
        }
        return value;
        });

          Boolean : true

          Boolean in number : 1

          Boolean in string : true

          在一定程序上来说,substitute 所提供的扩展性还是比较强的,不过另一方面的问题也就是 substitute 的功能有点弱了,Boolean 类型的数据也不能用,可能有些时候实现自己的字符串格式化函数还是有必要的。