本模块是用于扩展javascript语言能支持大多数ECMA262v5 API。因此对于像chrome,FF3,IE9,opera10,safari4等较新的浏览器,dom的模块加载器默认是不会再加载它。一般来说,我们需要加载的是语言扩展模块-lang,由它决定是否加载ecma模块。
//========================================= // ECMA262v5新扩展模块 //========================================== ;(function(global,DOC){ var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')]; dom.define("ecma", function(){ //Object扩展 //fix ie for..in bug var DONT_ENUM = dom.DONT_ENUM = [ 'propertyIsEnumerable', 'isPrototypeOf','hasOwnProperty','toLocaleString', 'toString', 'valueOf', 'constructor'], P = "prototype", H = dom.hasOwnProperty; for (var i in { toString: 1 }){ DONT_ENUM = false; } //第二个参数仅在浏览器支持Object.defineProperties时可用 dom.mix(Object,{ //取得其所有键名以数组形式返回 keys: function(obj){//ecma262v5 15.2.3.14 var result = []; for(var key in obj ) if(H.call(obj,key)){ result.push(key) } if(DONT_ENUM && obj){ var i = DONT_ENUM.length; while(( key = DONT_ENUM[i--])){ if(H.call(obj,key)){ result.push(key); } } } return result; }, getPrototypeOf : typeof P.__proto__ === "object" ? function(obj){ return obj.__proto__; }:function(obj){ return obj.constructor[P]; } },false); //用于创建javascript1.6 Array的迭代器 function iterator(vars, body, ret) { var fun = 'for(var '+vars+'i=0,n = this.length;i < n;i++){'+ body.replace('_', 'fn.call(scope,this[i],i,this)') +'}'+ret return new Function("fn,scope",fun); } dom.mix(Array[P],{ //定位类 返回指定项首次出现的索引。 indexOf: function (el, index) { var n = this.length, i = ~~index; if (i < 0) i += n; for (; i < n; i++) if ( this[i] === el) return i; return -1; }, //定位类 返回指定项最后一次出现的索引。 lastIndexOf: function (el, index) { var n = this.length, i = index == null ? n - 1 : index; if (i < 0) i = Math.max(0, n + i); for (; i >= 0; i--) if (this[i] === el) return i; return -1; }, //迭代类 在数组中的每个项上运行一个函数,若所有结果都返回真值,此方法亦返回真值。 forEach : iterator('', '_', ''), //迭代类 在数组中的每个项上运行一个函数,并将函数返回真值的项作为数组返回。 filter : iterator('r=[],j=0,', 'if(_)r[j++]=this[i]', 'return r'), //迭代类 在数组中的每个项上运行一个函数,并将全部结果作为数组返回。 map : iterator('r=[],', 'r[i]=_', 'return r'), //迭代类 在数组中的每个项上运行一个函数,若存在任意的结果返回真,则返回真值。 some : iterator('', 'if(_)return true', 'return false'), //迭代类 在数组中的每个项上运行一个函数,若所有结果都返回真值,此方法亦返回真值。 every : iterator('', 'if(!_)return false', 'return true'), //归化类 javascript1.8 对该数组的每项和前一次调用的结果运行一个函数,收集最后的结果。 reduce: function (fn, lastResult, scope) { if (this.length == 0) return lastResult; var i = lastResult !== undefined ? 0 : 1; var result = lastResult !== undefined ? lastResult : this[0]; for (var n = this.length; i < n; i++) result = fn.call(scope, result, this[i], i, this); return result; }, //归化类 javascript1.8 同上,但从右向左执行。 reduceRight: function (fn, lastResult, scope) { var array = this.concat().reverse(); return array.reduce(fn, lastResult, scope); } },false); //修正IE67下unshift不返回数组长度的问题 //http://www.cnblogs.com/rubylouvre/archive/2010/01/14/1647751.html if([].unshift(1) !== 1){ Array[P].unshift = function(){ var args = [0,0]; for(var i=0,n=arguments.length;i<n;i++){ args[args.length] = arguments[i] } Array[P].splice.apply(this, args); return this.length; //返回新数组的长度 } } if(!Array.isArray){ Array.isArray = function(obj){ return Object.prototype.toString.call(obj) =="[object Array]"; }; } //String扩展 var rtrim = /^(\u3000|\s|\t|\u00A0)*|(\u3000|\s|\t|\u00A0)*$/g; dom.mix(String[P],{ //ecma262v5 15.5.4.20 //http://www.cnblogs.com/rubylouvre/archive/2009/09/18/1568794.html // $$$$eq(' dfsd '.trim(),'dfsd') trim: function(){ return this.replace(rtrim,"") } },false); dom.mix(Function[P],{ //ecma262v5 15.3.4.5 bind:function(scope) { if (arguments.length < 2 && scope===void 0) return this; var fn = this, argv = arguments; return function() { var args = [], i; for(i = 1; i < argv.length; i++) args.push(argv[i]); for(i = 0; i < arguments.length; i++) args.push(arguments[i]); return fn.apply(scope, args); }; } },false); // Fix Date.get/setYear() (IE5-7) if ((new Date).getYear() > 1900) { Date.now = function(){ return +new Date; } //http://stackoverflow.com/questions/5763107/javascript-date-getyear-returns-different-result-between-ie-and-firefox-how-to Date[P].getYear = function() { return this.getFullYear() - 1900; }; Date[P].setYear = function(year) { return this.setFullYear(year + 1900); }; } }); })(this,this.document); //2011.7.26 移除Object.create方法,添加Object.getPrototypeOf方法 //2011.9.30 简化trim方法