本模块是用于扩展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方法