YUI学习笔记(3)

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

YAHOO.lang.later,YAHOO.lang.trim,YAHOO.lang.isXXX 以及 YAHOO.lang.hasOwnProperty。

1. YAHOO.lang.later(yahoo/yahoo.js)

later 方法用来延迟执行方法,是对 setInterval 和 setTimeout 的封装,并且可以传递参数到延迟执行的函数或者使用参数数组批量执行指定的函数。

later 方法的签名为:

later: function(when, o, fn, data, periodic)

when 是用来指定在多长时间后执行指定的函数,以毫秒计算;

o 是上下文对象,即在要执行的函数里使用 this 是会引用这个 o 对象;

fn 就是要延迟执行的函数了,可以传递一个函数引用,也可以传递一个字符串,later 方法会在 o 对象中查找对应名称的属性来做为要执行的方法;

data 就是传递给延迟执行的函数的参数了,可以为一个参数,或者是一个参数数组,那么如果我们要传递的参数本身就是一个数组的话,就要自己先把这个参数数组包装成一个数组;

peridoic 参数是一个布尔值,用来表示延迟执行的函数是否需要周期执行而不是只执行一次。

later 方法执行后会返回一个对象,包含了一个名 interval 的属性用来表示函数是以 setInterval 来执行的还是以 setTimeout 来执行的,以及一个方法 cancel 用来取消执行被延迟执行的函数。嗯,不过只有在 peridoic 为 true 时这个 cancel 方法比较有用,毕竟如果 peridoic 为 false 时函数执行一次就不会再执行了,cancel 也没有什么意义。

{
interval: periodic,
cancel: function() {
if (this.interval) {
clearInterval(r);
} else {
clearTimeout(r);
}
}
};

    2. YAHOO.lang.trim (yahoo/yahoo.js)

    trim 方法用来去除字符串两边的空白字符,其实也就用了一个正则来匹配字符串两端的空白字符并替换成空白字符串。

    不过在 YAHOO.lang.trim 中,它使用了一个 try … catch 来在调用的参数不为字符串时直接返回原来的对象。

    3. 对象类型判断 YAHOO.lang.isXXX (yahoo/yahoo.js)

    YAHOO.lang 中包含了一堆用于判断对象是否为某个类型的方法,例如 isObject、isString、isNumber 等。

    YAHOO.lang.isArray 用来判断一个对象是否为数组,YUI 中并不是使用的 obj instanceof Array 或者 obj.constructor == Array,而是判断指定的对象是否有两个数组应该具有的经典属性和方法 length 和 splice,这是因为如果要判断的对象是属于另外一个 frame 中时,除非你能获得另外一个 frame 中 Array 定义的费用,否则 instanceof 和 constructor == Array 都是返回 false 的,我们可以使用以下代码来测试一下:

    test.html

    <iframe id=”frame” src=”iframe.html”></iframe>
    <script type=”text/javascript”>
    <!–
    var f = document.getElementById(‘frame’);
    setTimeout(function() {
    alert(f.contentWindow.arr.constructor == Array);
    }, 1000);
    //–>
    </script>

      iframe.html

      <script type=”text/javascript”>
      <!–
      var arr = [1, 2, 3];
      //–>
      </script>

        而如果把 Array 换成 arr 所在 frame 中 Array 的引用,结果就是为 true 了:

        test.html

        <iframe id=”frame” src=”iframe.html”></iframe>
        <script type=”text/javascript”>
        <!–
        var f = document.getElementById(‘frame’);
        setTimeout(function() {
        // 这里将 Array 换成 f.contentWindow.Array
        alert(f.contentWindow.arr.constructor == f.contentWindow.Array);
        }, 1000);
        //–>
        </script>

          但是因为 isArray 是一个通用的方法,在使用时不可能要求调用者同时也传递一个目标 frame 的引用过来,所以只好通过判断两个经典的属性来代替了。

          YUI 的注释中提到是 Safari 不支持跨框架通过 instanceof 的检测,但是我测试的结果是几个主流浏览器都不支持跨框架的 instanceof 检测。

          YAHOO.lang.isBooleanYAHOO.lang.isFunctionYAHOO.lang.isStringYAHOO.lang.isUndefined 这 4 个方法是直接通过使用 typeof 来判断对象类型是否为 boolean、function、string 或 undefined 的。

          YAHOO.lang.isNumber 也是通过 typeof 来判断的,不过附加了一个检测条件,使用 isFinite 来检测数字是否为有限的,即不是 NaN、负无穷或正无穷。

          YAHOO.lang.isObject 通过 typeof 来判断对象类型是否 object 以及使用 isFunction 方法来检测对象是否为一个 Function,在 YAHOO.lang.isObject 方法的眼中,Object 与 Function 都是 Object。

          YAHOO.lang.isNull 直接将判断对象与 null 进行严格相等比较。

          YAHOO.lang.isValue 用来判断传递给它的参数是否为一个有值的对象,它是将 isObject、isString、isNumber 以及 isBoolean 四个方法对参数进行判断的结果进行或操作来作为结果的,对 null/undefined/NaN 这三个值进行 isValue 判断时就会返回 false,因为 0、false、’ 这三个值在分别在 isNumber、isBoolean、isString 时判断为 true,所有 isValue 的结果也为 true。

          4. YAHOO.lang.hasOwnProperty (yahoo/yahoo.js)

          嗯,这个方法也是对 Object.prototype.hasOwnProperty 的封装,前提是当前上下文的 Object.prototype 有 hasOwnProperty 方法,如果 Object.prototype.hasOwnProperty 不存在,那么 YAHOO.lang.hasOwnProperty 就实现了自己的 hasOwnProperty 方法,它是通过判断对象的属性与对象 prototype 的同名属性是否为同一个对象的判断的。如果对象的属性不是从原型继承过来的,那么两个属性值就有可能不一致:

          o.constructor.prototype[prop] !== o[prop]

          不过这里也有个问题,在 YAHOO.lang.hasOwnProperty 的注释中也提到了,就是 YUI 自己实现的 hasOwnProperty 是无法分辨在属性值一样时,这个属性是从原型继承过来的还是对象自身的:

          var YAHOO = {
          lang : {
          isUndefined : function(o) {
          return typeof o === “undefined”;
          },
          hasOwnProperty : function(o, prop) {
          return !this.isUndefined(o[prop]) &&
          o.constructor.prototype[prop] !== o[prop];
          }
          }
          }
          var A = function() {};
          A.prototype.foo = ‘foo’;
          var a = new A();
          a.foo = ‘foo’;
          alert(a.hasOwnProperty(‘foo’)); // true
          alert(YAHOO.lang.hasOwnProperty(a, ‘foo’)); // 这里返回 false,事实上应该是 true

            但是现在 Object.prototype 中没有 hasOwnProperty 的浏览器应该基本没有了,所以这个问题也不是很大。

            5. YAHOO.lang.augmentProto 以及 YAHOO.lang.extend 的别名 (yahoo/yahoo.js)

            在 yahoo.js 中,将 YAHOO.lang.augment 以及 YAHOO.augment 指向了 YAHOO.lang.augmentProto,YAHOO.extend 指向了 YAHOO.lang.extend,可以一定程度上减少代码的编写。