1 2 /** 3 * 2.[Javascript core]: 常用工具函数扩展 4 */ 5 Jx().$package(function(J){ 6 var isUndefined, 7 isNull, 8 isNumber, 9 isString, 10 isBoolean, 11 isObject, 12 isArray, 13 isArguments, 14 isFunction, 15 $typeof, 16 17 $return, 18 $try, 19 20 emptyFunc, 21 22 checkJSON, 23 random, 24 extend, 25 clone, 26 now, 27 timedChunk, 28 29 getLength, 30 31 32 rebuild, 33 pass, 34 bind, 35 bindNoEvent, 36 37 38 39 40 Class; 41 42 /** 43 * 判断变量的值是否是 undefined 44 * Determines whether or not the provided object is undefined 45 * 46 * @method isUndefined 47 * @memberOf Jx.prototype 48 * 49 * @param {Mixed} o 传入被检测变量的名称 50 * @return {Boolean} 当 o 的值是 undefined 时返回 true 51 */ 52 isUndefined = function(o) { 53 return typeof(o) === "undefined"; 54 }; 55 56 /** 57 * 判断变量的值是否是 null 58 * Determines whether or not the provided object is null 59 * 60 * @method isNull 61 * @memberOf Jx.prototype 62 * 63 * @param {Mixed} o 传入被检测变量的名称 64 * @return {Boolean} 当 o 的值是 null 时返回 true 65 */ 66 isNull = function(o) { 67 return o === null; 68 }; 69 70 /** 71 * 判断变量的类型是否是 Number 72 * Determines whether or not the provided object is a number 73 * 74 * @memberOf Jx.prototype 75 * @name isNumber 76 * @function 77 * @param {Mixed} o 传入被检测变量的名称 78 * @return {Boolean} 当 o 的类型是 number 时返回 true 79 */ 80 isNumber = function(o) { 81 return (o === 0 || o) && o.constructor === Number; 82 }; 83 84 /** 85 * 判断变量的类型是否是 Boolean 86 * Determines whether or not the provided object is a boolean 87 * 88 * 89 * @method isBoolean 90 * @memberOf Jx.prototype 91 * 92 * @static 93 * @param {Mixed} o 传入被检测变量的名称 94 * @return {Boolean} 当 o 的类型是 boolean 时返回 true 95 */ 96 isBoolean = function(o) { 97 return (o === false || o) && (o.constructor === Boolean); 98 }; 99 100 /** 101 * 判断变量的类型是否是 String 102 * Determines whether or not the provided object is a string 103 * 104 * 105 * @method isString 106 * @memberOf Jx.prototype 107 * 108 * @static 109 * @param {Mixed} o 传入被检测变量的名称 110 * @return {Boolean} 当 o 的类型是 string 时返回 true 111 */ 112 isString = function(o) { 113 return (o === "" || o) && (o.constructor === String); 114 }; 115 116 /** 117 * 判断变量的类型是否是 Object 118 * Determines whether or not the provided object is a object 119 * 120 * 121 * @method isObject 122 * @memberOf Jx.prototype 123 * 124 * @param {Mixed} o 传入被检测变量的名称 125 * @return {Boolean} 当 o 的类型是 object 时返回 true 126 */ 127 isObject = function(o) { 128 return o && (o.constructor === Object || Object.prototype.toString.call(o) === "[object Object]"); 129 }; 130 131 /** 132 * 判断变量的类型是否是 Array 133 * Determines whether or not the provided object is a array 134 * 135 * 136 * @method isArray 137 * @memberOf Jx.prototype 138 * 139 * @param {Mixed} o 传入被检测变量的名称 140 * @return {Boolean} 当 o 的类型是 array 时返回 true 141 */ 142 isArray = function(o) { 143 return o && (o.constructor === Array || Object.prototype.toString.call(o) === "[object Array]"); 144 }; 145 146 /** 147 * 判断变量的类型是否是 Arguments 148 * Determines whether or not the provided object is a arguments 149 * 150 * 151 * @method isArguments 152 * @memberOf Jx.prototype 153 * 154 * @param {Mixed} o 传入被检测变量的名称 155 * @return {Boolean} 当 o 的类型是 arguments 时返回 true 156 */ 157 isArguments = function(o) { 158 return o && o.callee && isNumber(o.length) ? true : false; 159 }; 160 161 /** 162 * 判断变量的类型是否是 Function 163 * Determines whether or not the provided object is a function 164 * 165 * 166 * @method isFunction 167 * @memberOf Jx.prototype 168 * 169 * @param {Mixed} o 传入被检测变量的名称 170 * @return {Boolean} 当 o 的类型是 function 时返回 true 171 */ 172 isFunction = function(o) { 173 return o && (o.constructor === Function); 174 }; 175 176 /** 177 * 判断变量类型的方法 178 * Determines the type of object 179 * 180 * 181 * @method $typeof 182 * @memberOf Jx.prototype 183 * 184 * @param {Mixed} o 传入被检测变量的名称 185 * @return {String} 返回变量的类型,如果不识别则返回 other 186 */ 187 $typeof = function(o) { 188 if(isUndefined(o)){ 189 return "undefined"; 190 }else if(isNull(o)){ 191 return "null"; 192 }else if(isNumber(o)){ 193 return "number"; 194 }else if(isBoolean(o)){ 195 return "boolean"; 196 }else if(isString(o)){ 197 return "string"; 198 }else if(isObject(o)){ 199 return "object"; 200 }else if(isArray(o)){ 201 return "array"; 202 }else if(isArguments(o)){ 203 return "arguments"; 204 }else if(isFunction(o)){ 205 return "function"; 206 }else{ 207 return "other"; 208 } 209 210 }; 211 /** 212 * @ignore 213 */ 214 checkJSON = function(){ 215 216 return true; 217 }; 218 219 /** 220 * 生成随机数的方法 221 * 222 * @method random 223 * @memberOf Jx.prototype 224 * 225 * @param {Number} min 生成随机数的最小值 226 * @param {Number} max 生成随机数的最大值 227 * @return {Number} 返回生成的随机数 228 */ 229 random = function(min, max){ 230 return Math.floor(Math.random() * (max - min + 1) + min); 231 }; 232 233 234 235 /** 236 * 克隆一个对象 237 * 238 * @method clone 239 * @memberOf Jx.prototype 240 * 241 * @param {Object} o 要克隆的对象 242 * @return {Object} 返回通过克隆创建的对象 243 * 244 * @example 245 * Jx().$package(function(J){ 246 * var objA = {name: "Kinvix"}; 247 * // 克隆一个 objA 对象,并存入 objB 中。 248 * var objB = J.clone(objA); 249 * }; 250 */ 251 clone = function(o){ 252 /** 253 * @ignore 254 */ 255 var tempClass = function(){}; 256 tempClass.prototype = o; 257 258 // 返回新克隆的对象 259 return (new tempClass()); 260 }; 261 262 263 264 265 266 267 268 269 /** 270 * 生成一个返回值是传入的 value 值的函数 271 * 272 * @method $return 273 * @memberOf Jx.prototype 274 * 275 * @param {Mixed} value 要返回的值 276 * @return {Mixed} 返回一个返回值是 value 的函数 277 */ 278 $return = function(result){ 279 return J.isFunction(result) ? result : function(){ 280 return result; 281 }; 282 }; 283 284 /** 285 * 从第一个函数开始try,直到尝试出第一个可以成功执行的函数就停止继续后边的函数,并返回这个个成功执行的函数结果 286 * 287 * @method $try 288 * @memberOf Jx.prototype 289 * 290 * @param {Function} fn1, fn2, .... 要尝试的函数 291 * @return {Mixed} 返回第一个成功执行的函数的返回值 292 * 293 * @example 294 * Jx().$package(function(J){ 295 * // 按顺序执行 funcA, funcB, funcC,当中途有一个 func 的执行结果返回 true 则不再往下执行,并返回成功执行的 func 的返回值; 296 * J.$try(funcA, funcB, funcC); 297 * }; 298 */ 299 $try = function(){ 300 var i, 301 l = arguments.length, 302 result; 303 304 for(i = 0; i < l; i++){ 305 try{ 306 result = arguments[i](); 307 // 如果上边语句执行成功则执行break跳出循环 308 break; 309 }catch(e){ 310 J.out("C.错误:[" + e.name + "] "+e.message+", " + e.fileName+", 行号:"+e.lineNumber+"; stack:"+typeof e.stack, 2); 311 } 312 } 313 return result; 314 }; 315 316 /** 317 * 对一个对象或数组进行扩展 318 * 319 * @method extend 320 * @memberOf Jx.prototype 321 * 322 * @param {Mixed} beExtendObj 被扩展的对象或数组 323 * @param {Mixed} extendObj1, extendObj2, .... 用来参照扩展的对象或数组 324 * @return {Mixed} 返回被扩展后的对象或数组 325 * 326 * @example 327 * Jx().$package(function(J){ 328 * // 用 objB 和objC 扩展 objA 对象; 329 * J.extend(objA, objB, objC); 330 * }; 331 * 332 */ 333 extend = function(beExtendObj, extendObj1, extendObj2){ 334 var a = arguments, 335 i, 336 p, 337 beExtendObj, 338 extendObj; 339 340 if(a.length === 1){ 341 beExtendObj = this; 342 i=0; 343 }else{ 344 beExtendObj = a[0] || {}; 345 i=1; 346 } 347 348 for(; i<arguments.length; i++){ 349 extendObj = arguments[i]; 350 for(p in extendObj){ 351 var src = beExtendObj[p], 352 obj = extendObj[p]; 353 if ( src === obj ){ 354 continue; 355 } 356 357 if ( obj && isObject(obj) && !isArray(obj) && !obj.nodeType && !isFunction(obj)){ 358 src = beExtendObj[p] || {};//2010-12-28 359 beExtendObj[p] = extend( src, 360 // Never move original objects, clone them 361 obj || ( obj.length != null ? [ ] : { } )); 362 363 // Don't bring in undefined values 364 }else if ( obj !== undefined ){ 365 beExtendObj[p] = obj; 366 } 367 } 368 } 369 370 return beExtendObj; 371 }; 372 373 374 /* 375 extend = function(beExtendObj, target, extendObj2) { 376 377 // copy reference to target object 378 var target = arguments[0] || {}, 379 i = 2, 380 length = arguments.length, 381 options; 382 383 384 target = arguments[1] || {}; 385 386 387 388 // Handle case when target is a string or something (possible in deep copy) 389 if ( typeof target !== "object" && !J.isFunction(target) ){ 390 target = {}; 391 } 392 // extend jQuery itself if only one argument is passed 393 if ( length == i ) { 394 target = this; 395 --i; 396 } 397 398 for ( ; i < length; i++ ){ 399 // Only deal with non-null/undefined values 400 if ( (options = arguments[ i ]) != null ){ 401 // Extend the base object 402 for ( var name in options ) { 403 var src = target[ name ], 404 copy = options[ name ]; 405 406 // Prevent never-ending loop 407 if ( target === copy ){ 408 continue; 409 } 410 // Recurse if we're merging object values 411 if ( copy && typeof copy === "object" && !copy.nodeType ){ 412 target[ name ] = extend( target, 413 // Never move original objects, clone them 414 src || ( copy.length != null ? [ ] : { } ) 415 , copy ); 416 417 // Don't bring in undefined values 418 }else if ( copy !== undefined ){ 419 target[ name ] = copy; 420 } 421 } 422 } 423 } 424 // Return the modified object 425 return target; 426 }; 427 */ 428 429 /** 430 * 获取当前时间的函数 431 * 432 * @method now 433 * @memberOf Jx.prototype 434 * 435 * 436 * 437 * @example 438 * alert(J.now()); 439 * 440 */ 441 now = function(){ 442 return +new Date; 443 } 444 445 446 /** 447 * 通用分时处理函数 448 * 449 * @method timedChunk 450 * @memberOf Jx.prototype 451 * 452 * 453 * 454 * @example 455 * Jx().$package(function(J){ 456 * }; 457 * 458 */ 459 timedChunk = function(items, process, context, isShift, callback) { 460 var todo = items.concat(), delay = 25; 461 if(isShift){ 462 todo = items; 463 } 464 465 window.setTimeout(function() { 466 var start = +new Date(); 467 468 do { 469 process.call(context, todo.shift()); 470 } while(todo.length > 0 && (+new Date() - start < 50)); 471 472 if(todo.length > 0) { 473 window.setTimeout(arguments.callee, delay); 474 } else if(callback) { 475 callback(items); 476 } 477 478 }, delay); 479 } 480 481 482 483 /** 484 * 获取对象自身具有的属性和方法的数量 485 * 486 * @method getLength 487 * @memberOf Jx.prototype 488 * 489 * @param {Object} obj 要获取的对象 490 * @return {Number} 返回对象自身具有属性和方法的数量 491 */ 492 getLength = function(obj) { 493 var p, 494 count = 0; 495 for(p in obj){ 496 if(obj.hasOwnProperty(p)){ 497 count++; 498 } 499 } 500 return count; 501 }; 502 503 /** 504 * 一个空函数函数 505 * 506 * @memberOf Jx.prototype 507 */ 508 emptyFunc = function(){}; 509 510 511 512 513 /** 514 * 函数的重构方法 515 * 516 * 517 * @private 518 * @memberOf Jx.prototype 519 * @param {Object} option 选项对象 520 * @return {Function} 返回重构后的函数的执行结果 521 */ 522 rebuild = function(func, option){ 523 option = option || {}; 524 525 func.$$rebuildedFunc = func.$$rebuildedFunc || function(){ 526 var self2 = this, 527 scope, 528 args, 529 returns; 530 scope = option.contextObj || self2; 531 args = Array.prototype.slice.call(arguments, 0); 532 533 if(args !== undefined){ 534 args = args.concat(option.arguments); 535 } 536 if(option.event === false){ 537 args = args.slice(1); 538 } 539 540 return func.apply(scope, args); 541 }; 542 543 return func.$$rebuildedFunc; 544 }; 545 546 /** 547 * 给函数传入参数并执行 548 * 549 * @memberOf Jx.prototype 550 * @param {Mixed} args 参数列表 551 * @return {Mixed} 返回函数执行结果 552 * 553 * @example 554 * Jx().$package(function(J){ 555 * // 将"a"、"b"两个字符串传入funcA函数并执行 556 * funcA.pass("a","b"); 557 * }; 558 * 559 */ 560 pass = function(func, var_args) { 561 var slice = Array.prototype.slice; 562 var a = slice.call(arguments, 1); 563 return function(){ 564 var context = this; 565 return func.apply(context, a.concat(slice.call(arguments))); 566 }; 567 }; 568 /* 569 pass = function(func){ 570 var args = Array.prototype.slice.call(arguments, 1); 571 return rebuild(func, {contextObj: null, arguments: args}); 572 }; 573 */ 574 575 /* 576 * 给函数绑定一个上下文对象再执行 577 * 578 * @memberOf Jx.prototype 579 * @param {Object} contextObj 要绑定的上下文对象 580 * @param {Mixed} args 参数列表 581 * @return {Mixed} 返回函数执行结果 582 * 583 * @example 584 * Jx().$package(function(J){ 585 * // 以 contextObjB 对象为上下文对象 this 来执行funcA函数 586 * funcA.bind(contextObjB); 587 * }; 588 * 589 */ 590 /* 591 bind = function(func, contextObj){ 592 var args = Array.prototype.slice.call(arguments, 2); 593 //args = [this].extend(args); 594 return rebuild(func, {contextObj: contextObj, arguments: args}); 595 }; 596 */ 597 598 /** 599 * 将一个函数绑定给一个对象作方法,返回的函数将总被传入{@code obj} as {@code this} 600 * 601 * @memberOf Jx.prototype 602 * @param {Function} func 要绑定的函数 603 * @param {Object} contextObj 要绑定的对象 604 * @param {Mixed} args 参数列表,长度任意 605 * @return {Function} 返回一个被绑定this上下文对象的函数 606 * 607 * @example 608 * Jx().$package(function(J){ 609 * funcB = J.bind(funcA, obj, a, b) 610 * funcB(c, d) // 相当于执行 funcA.call(obj, a, b, c, d) 611 * }; 612 */ 613 614 bind = function(func, context, var_args) { 615 var slice = Array.prototype.slice; 616 var a = slice.call(arguments, 2); 617 return function(){ 618 return func.apply(context, a.concat(slice.call(arguments))); 619 }; 620 }; 621 622 623 624 625 626 627 628 629 /** 630 * 创建Class类的类 631 * Class 632 * @class 633 * @memberOf Jx 634 * @param {Object} option = {extend: superClass} 在option对象的extend属性中指定要继承的对象,可以不写 635 * @param {Object} object 扩展的对象 636 * @return {Object} 返回生成的日期时间字符串 637 * 638 * @example 639 * Jx().$package(function(J){ 640 * var Person = new J.Class({ 641 * init : function(name){ 642 * this.name = name; 643 * alert("init"); 644 * }, 645 * showName : function(){ 646 * alert(this.name); 647 * 648 * } 649 * 650 * }); 651 * 652 * // 继承Person 653 * var Person2 = new J.Class({extend : Person}, { 654 * init : function(name){ 655 * this.name = name; 656 * alert("init"); 657 * }, 658 * showName : function(){ 659 * alert(this.name); 660 * 661 * } 662 * 663 * }); 664 * 665 * }; 666 * 667 */ 668 Class = function(){ 669 var length = arguments.length; 670 var option = arguments[length-1]; 671 672 option.init = option.init || function(){}; 673 674 // 如果参数中有要继承的父类 675 if(length === 2){ 676 /** 677 * @ignore 678 */ 679 var superClass = arguments[0].extend; 680 681 /** 682 * @ignore 683 */ 684 var tempClass = function() {}; 685 tempClass.prototype = superClass.prototype; 686 687 /** 688 * @ignore 689 */ 690 var subClass = function() { 691 this.init.apply(this, arguments); 692 } 693 694 // 加一个对父类原型引用的静态属性 695 subClass.superClass = superClass.prototype; 696 //subClass.superClass = superClass; 697 /** 698 * @ignore 699 */ 700 subClass.callSuper = function(context,func){ 701 var slice = Array.prototype.slice; 702 var a = slice.call(arguments, 2); 703 var func = subClass.superClass[func]; 704 //var func = subClass.superClass.prototype[func]; 705 if(func){ 706 func.apply(context, a.concat(slice.call(arguments))); 707 } 708 }; 709 710 // 指定原型 711 subClass.prototype = new tempClass(); 712 713 // 重新指定构造函数 714 subClass.prototype.constructor = subClass; 715 716 J.extend(subClass.prototype, option); 717 718 /** 719 * @ignore 720 */ 721 subClass.prototype.init = function(){ 722 // 调用父类的构造函数 723 // subClass.superClass.init.apply(this, arguments); 724 // 调用此类自身的构造函数 725 option.init.apply(this, arguments); 726 }; 727 728 return subClass; 729 730 // 如果参数中没有父类,则单纯构建一个类 731 }else if(length === 1){ 732 /** 733 * @ignore 734 */ 735 var newClass = function() { 736 // 加了return,否则init返回的对象不生效 737 return this.init.apply(this, arguments); 738 } 739 newClass.prototype = option; 740 return newClass; 741 } 742 743 744 }; 745 746 var Chunk = new Class({ 747 init : function(items, process, context, isShift, callback) { 748 var todo = items.concat(), delay = 25; 749 if(isShift){ 750 todo = items; 751 } 752 //this.timeout; 753 this.timeout = window.setTimeout(function() { 754 var start = +new Date(); 755 756 do { 757 process.call(context, todo.shift()); 758 } while(todo.length > 0 && (+new Date() - start < 50)); 759 760 if(todo.length > 0) { 761 this.timeout = window.setTimeout(arguments.callee, delay); 762 } else if(callback) { 763 callback(items); 764 } 765 766 }, delay); 767 }, 768 stop : function(){ 769 clearTimeout(this.timeout); 770 } 771 772 }); 773 /* 774 Class = function(obj){ 775 var tempClass = function() { 776 this.init.apply(this, arguments); 777 } 778 tempClass.prototype = obj; 779 return tempClass; 780 }; 781 */ 782 783 784 785 786 787 J.isUndefined = isUndefined; 788 J.isNull = isNull; 789 J.isNumber = isNumber; 790 J.isString = isString; 791 J.isBoolean = isBoolean; 792 J.isObject = isObject; 793 J.isArray = isArray; 794 J.isArguments = isArguments; 795 J.isFunction = isFunction; 796 J.$typeof = $typeof; 797 798 J.$return = $return; 799 J.$try = $try; 800 801 J.emptyFunc = emptyFunc; 802 803 J.clone = clone; 804 805 J.getLength = getLength; 806 J.checkJSON = checkJSON; 807 J.random = random; 808 J.extend = extend; 809 810 J.now = now; 811 J.timedChunk = timedChunk; 812 813 814 J.rebuild = rebuild; 815 J.pass = pass; 816 J.bind = bind; 817 J.bindNoEvent = bindNoEvent; 818 819 820 821 J.Class = Class; 822 J.Chunk = Chunk; 823 824 825 826 }); 827