ECMAScript5新增的方法

// Copyright 2009-2012 by contributors, MIT License
// vim: ts=4 sts=4 sw=4 expandtab
 
// Module systems magic dance
(function (definition) {
    // RequireJS
    if (typeof define == "function") {
        define(definition);
    // YUI3
    } else if (typeof YUI == "function") {
        YUI.add("es5-sham", definition);
    // CommonJS and <script>
    } else {
        definition();
    }
})(function () {
 
// ES5 15.2.3.2
// http://es5.github.com/#x15.2.3.2
if (!Object.getPrototypeOf) {
    // https://github.com/kriskowal/es5-shim/issues#issue/2
    // http://ejohn.org/blog/objectgetprototypeof/
    // recommended by fschaefer on github
    Object.getPrototypeOf = function getPrototypeOf(object) {
        return object.__proto__ || (
            object.constructor
                ? object.constructor.prototype
                : prototypeOfObject
        );
    };
}
 
// ES5 15.2.3.3
// http://es5.github.com/#x15.2.3.3
if (!Object.getOwnPropertyDescriptor) {
    var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a non-object: ";
 
    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
        if ((typeof object != "object" && typeof object != "function") || object === null) {
            throw new TypeError(ERR_NON_OBJECT + object);
        }
        // If object does not owns property return undefined immediately.
        if (!owns(object, property)) {
            return;
        }
 
        // If object has a property then it's for sure both `enumerable` and
        // `configurable`.
        var descriptor =  { enumerable: true, configurable: true };
 
        // If JS engine supports accessor properties then property may be a
        // getter or setter.
        if (supportsAccessors) {
            // Unfortunately `__lookupGetter__` will return a getter even
            // if object has own non getter property along with a same named
            // inherited getter. To avoid misbehavior we temporary remove
            // `__proto__` so that `__lookupGetter__` will return getter only
            // if it's owned by an object.
            var prototype = object.__proto__;
            object.__proto__ = prototypeOfObject;
 
            var getter = lookupGetter(object, property);
            var setter = lookupSetter(object, property);
 
            // Once we have getter and setter we can put values back.
            object.__proto__ = prototype;
 
            if (getter || setter) {
                if (getter) {
                    descriptor.get = getter;
                }
                if (setter) {
                    descriptor.set = setter;
                }
                // If it was accessor property we're done and return here
                // in order to avoid adding `value` to the descriptor.
                return descriptor;
            }
        }
 
        // If we got this far we know that object has an own property that is
        // not an accessor so we set it as a value and return descriptor.
        descriptor.value = object[property];
        return descriptor;
    };
}
 
// ES5 15.2.3.4
// http://es5.github.com/#x15.2.3.4
if (!Object.getOwnPropertyNames) {
    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
        return Object.keys(object);
    };
}
 
// ES5 15.2.3.5
// http://es5.github.com/#x15.2.3.5
if (!Object.create) {
 
    // Contributed by Brandon Benvie, October, 2012
    var createEmpty;
    var supportsProto = Object.prototype.__proto__ === null;
    if (supportsProto || typeof document == 'undefined') {
        createEmpty = function () {
            return { "__proto__": null };
        };
    } else {
        // In old IE __proto__ can't be used to manually set `null`, nor does
        // any other method exist to make an object that inherits from nothing,
        // aside from Object.prototype itself. Instead, create a new global
        // object and *steal* its Object.prototype and strip it bare. This is
        // used as the prototype to create nullary objects.
        createEmpty = (function () {
            var iframe = document.createElement('iframe');
            var parent = document.body || document.documentElement;
            iframe.style.display = 'none';
            parent.appendChild(iframe);
            iframe.src = 'javascript:';
            var empty = iframe.contentWindow.Object.prototype;
            parent.removeChild(iframe);
            iframe = null;
            delete empty.constructor;
            delete empty.hasOwnProperty;
            delete empty.propertyIsEnumerable;
            delete empty.isPrototypeOf;
            delete empty.toLocaleString;
            delete empty.toString;
            delete empty.valueOf;
            empty.__proto__ = null;
 
            function Empty() {}
            Empty.prototype = empty;
 
            return function () {
                return new Empty();
            };
        })();
    }
 
    Object.create = function create(prototype, properties) {
 
        var object;
        function Type() {}  // An empty constructor.
 
        if (prototype === null) {
            object = createEmpty();
        } else {
            if (typeof prototype !== "object" && typeof prototype !== "function") {
                // In the native implementation `parent` can be `null`
                // OR *any* `instanceof Object`  (Object|Function|Array|RegExp|etc)
                // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object`
                // like they are in modern browsers. Using `Object.create` on DOM elements
                // is...err...probably inappropriate, but the native version allows for it.
                throw new TypeError("Object prototype may only be an Object or null"); // same msg as Chrome
            }
            Type.prototype = prototype;
            object = new Type();
            // IE has no built-in implementation of `Object.getPrototypeOf`
            // neither `__proto__`, but this manually setting `__proto__` will
            // guarantee that `Object.getPrototypeOf` will work as expected with
            // objects created using `Object.create`
            object.__proto__ = prototype;
        }
 
        if (properties !== void 0) {
            Object.defineProperties(object, properties);
        }
 
        return object;
    };
}
 
// ES5 15.2.3.6
// http://es5.github.com/#x15.2.3.6
 
// Patch for WebKit and IE8 standard mode
// Designed by hax <hax.github.com>
// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5
// IE8 Reference:
//     http://msdn.microsoft.com/en-us/library/dd282900.aspx
//     http://msdn.microsoft.com/en-us/library/dd229916.aspx
// WebKit Bugs:
//     https://bugs.webkit.org/show_bug.cgi?id=36423
 
function doesDefinePropertyWork(object) {
    try {
        Object.defineProperty(object, "sentinel", {});
        return "sentinel" in object;
    } catch (exception) {
        // returns falsy
    }
}
 
// check whether defineProperty works if it's given. Otherwise,
// shim partially.
if (Object.defineProperty) {
    var definePropertyWorksOnObject = doesDefinePropertyWork({});
    var definePropertyWorksOnDom = typeof document == "undefined" ||
        doesDefinePropertyWork(document.createElement("div"));
    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
        var definePropertyFallback = Object.defineProperty,
            definePropertiesFallback = Object.defineProperties;
    }
}
 
if (!Object.defineProperty || definePropertyFallback) {
    var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
    var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
    var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
                                      "on this javascript engine";
 
    Object.defineProperty = function defineProperty(object, property, descriptor) {
        if ((typeof object != "object" && typeof object != "function") || object === null) {
            throw new TypeError(ERR_NON_OBJECT_TARGET + object);
        }
        if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) {
            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
        }
        // make a valiant attempt to use the real defineProperty
        // for I8's DOM elements.
        if (definePropertyFallback) {
            try {
                return definePropertyFallback.call(Object, object, property, descriptor);
            } catch (exception) {
                // try the shim if the real one doesn't work
            }
        }
 
        // If it's a data property.
        if (owns(descriptor, "value")) {
            // fail silently if "writable", "enumerable", or "configurable"
            // are requested but not supported
            /*
            // alternate approach:
            if ( // can't implement these features; allow false but not true
                !(owns(descriptor, "writable") ? descriptor.writable : true) ||
                !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
                !(owns(descriptor, "configurable") ? descriptor.configurable : true)
            )
                throw new RangeError(
                    "This implementation of Object.defineProperty does not " +
                    "support configurable, enumerable, or writable."
                );
            */
 
            if (supportsAccessors && (lookupGetter(object, property) ||
                                      lookupSetter(object, property)))
            {
                // As accessors are supported only on engines implementing
                // `__proto__` we can safely override `__proto__` while defining
                // a property to make sure that we don't hit an inherited
                // accessor.
                var prototype = object.__proto__;
                object.__proto__ = prototypeOfObject;
                // Deleting a property anyway since getter / setter may be
                // defined on object itself.
                delete object[property];
                object[property] = descriptor.value;
                // Setting original `__proto__` back now.
                object.__proto__ = prototype;
            } else {
                object[property] = descriptor.value;
            }
        } else {
            if (!supportsAccessors) {
                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
            }
            // If we got that far then getters and setters can be defined !!
            if (owns(descriptor, "get")) {
                defineGetter(object, property, descriptor.get);
            }
            if (owns(descriptor, "set")) {
                defineSetter(object, property, descriptor.set);
            }
        }
        return object;
    };
}
 
// ES5 15.2.3.7
// http://es5.github.com/#x15.2.3.7
if (!Object.defineProperties || definePropertiesFallback) {
    Object.defineProperties = function defineProperties(object, properties) {
        // make a valiant attempt to use the real defineProperties
        if (definePropertiesFallback) {
            try {
                return definePropertiesFallback.call(Object, object, properties);
            } catch (exception) {
                // try the shim if the real one doesn't work
            }
        }
         
        for (var property in properties) {
            if (owns(properties, property) && property != "__proto__") {
                Object.defineProperty(object, property, properties[property]);
            }
        }
        return object;
    };
}
 
// ES5 15.2.3.8
// http://es5.github.com/#x15.2.3.8
if (!Object.seal) {
    Object.seal = function seal(object) {
        // this is misleading and breaks feature-detection, but
        // allows "securable" code to "gracefully" degrade to working
        // but insecure code.
        return object;
    };
}
 
// ES5 15.2.3.9
// http://es5.github.com/#x15.2.3.9
if (!Object.freeze) {
    Object.freeze = function freeze(object) {
        // this is misleading and breaks feature-detection, but
        // allows "securable" code to "gracefully" degrade to working
        // but insecure code.
        return object;
    };
}
 
// detect a Rhino bug and patch it
try {
    Object.freeze(function () {});
} catch (exception) {
    Object.freeze = (function freeze(freezeObject) {
        return function freeze(object) {
            if (typeof object == "function") {
                return object;
            } else {
                return freezeObject(object);
            }
        };
    })(Object.freeze);
}
 
// ES5 15.2.3.10
// http://es5.github.com/#x15.2.3.10
if (!Object.preventExtensions) {
    Object.preventExtensions = function preventExtensions(object) {
        // this is misleading and breaks feature-detection, but
        // allows "securable" code to "gracefully" degrade to working
        // but insecure code.
        return object;
    };
}
 
// ES5 15.2.3.11
// http://es5.github.com/#x15.2.3.11
if (!Object.isSealed) {
    Object.isSealed = function isSealed(object) {
        return false;
    };
}
 
// ES5 15.2.3.12
// http://es5.github.com/#x15.2.3.12
if (!Object.isFrozen) {
    Object.isFrozen = function isFrozen(object) {
        return false;
    };
}
 
// ES5 15.2.3.13
// http://es5.github.com/#x15.2.3.13
if (!Object.isExtensible) {
    Object.isExtensible = function isExtensible(object) {
        // 1. If Type(O) is not Object throw a TypeError exception.
        if (Object(object) !== object) {
            throw new TypeError(); // TODO message
        }
        // 2. Return the Boolean value of the [[Extensible]] internal property of O.
        var name = '';
        while (owns(object, name)) {
            name += '?';
        }
        object[name] = true;
        var returnValue = owns(object, name);
        delete object[name];
        return returnValue;
    };
}
 
});
 
//----------------------------------------------------------------------//
 
//Copyright 2009-2012 by contributors, MIT License
//vim: ts=4 sts=4 sw=4 expandtab
 
//Module systems magic dance
(function (definition) {
 // RequireJS
 if (typeof define == "function") {
     define(definition);
 // YUI3
 } else if (typeof YUI == "function") {
     YUI.add("es5", definition);
 // CommonJS and <script>
 } else {
     definition();
 }
})(function () {
 
/**
* Brings an environment as close to ECMAScript 5 compliance
* as is possible with the facilities of erstwhile engines.
*
* Annotated ES5: http://es5.github.com/ (specific links below)
* ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
* Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
*/
 
//
//Function
//========
//
 
//ES-5 15.3.4.5
//http://es5.github.com/#x15.3.4.5
 
function Empty() {}
 
if (!Function.prototype.bind) {
 Function.prototype.bind = function bind(that) { // .length is 1
     // 1. Let Target be the this value.
     var target = this;
     // 2. If IsCallable(Target) is false, throw a TypeError exception.
     if (typeof target != "function") {
         throw new TypeError("Function.prototype.bind called on incompatible " + target);
     }
     // 3. Let A be a new (possibly empty) internal list of all of the
     //   argument values provided after thisArg (arg1, arg2 etc), in order.
     // XXX slicedArgs will stand in for "A" if used
     var args = slice.call(arguments, 1); // for normal call
     // 4. Let F be a new native ECMAScript object.
     // 11. Set the [[Prototype]] internal property of F to the standard
     //   built-in Function prototype object as specified in 15.3.3.1.
     // 12. Set the [[Call]] internal property of F as described in
     //   15.3.4.5.1.
     // 13. Set the [[Construct]] internal property of F as described in
     //   15.3.4.5.2.
     // 14. Set the [[HasInstance]] internal property of F as described in
     //   15.3.4.5.3.
     var bound = function () {
 
         if (this instanceof bound) {
             // 15.3.4.5.2 [[Construct]]
             // When the [[Construct]] internal method of a function object,
             // F that was created using the bind function is called with a
             // list of arguments ExtraArgs, the following steps are taken:
             // 1. Let target be the value of F's [[TargetFunction]]
             //   internal property.
             // 2. If target has no [[Construct]] internal method, a
             //   TypeError exception is thrown.
             // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
             //   property.
             // 4. Let args be a new list containing the same values as the
             //   list boundArgs in the same order followed by the same
             //   values as the list ExtraArgs in the same order.
             // 5. Return the result of calling the [[Construct]] internal
             //   method of target providing args as the arguments.
 
             var result = target.apply(
                 this,
                 args.concat(slice.call(arguments))
             );
             if (Object(result) === result) {
                 return result;
             }
             return this;
 
         } else {
             // 15.3.4.5.1 [[Call]]
             // When the [[Call]] internal method of a function object, F,
             // which was created using the bind function is called with a
             // this value and a list of arguments ExtraArgs, the following
             // steps are taken:
             // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
             //   property.
             // 2. Let boundThis be the value of F's [[BoundThis]] internal
             //   property.
             // 3. Let target be the value of F's [[TargetFunction]] internal
             //   property.
             // 4. Let args be a new list containing the same values as the
             //   list boundArgs in the same order followed by the same
             //   values as the list ExtraArgs in the same order.
             // 5. Return the result of calling the [[Call]] internal method
             //   of target providing boundThis as the this value and
             //   providing args as the arguments.
 
             // equiv: target.call(this, ...boundArgs, ...args)
             return target.apply(
                 that,
                 args.concat(slice.call(arguments))
             );
 
         }
 
     };
     if(target.prototype) {
         Empty.prototype = target.prototype;
         bound.prototype = new Empty();
         // Clean up dangling references.
         Empty.prototype = null;
     }
     // XXX bound.length is never writable, so don't even try
     //
     // 15. If the [[Class]] internal property of Target is "Function", then
     //     a. Let L be the length property of Target minus the length of A.
     //     b. Set the length own property of F to either 0 or L, whichever is
     //       larger.
     // 16. Else set the length own property of F to 0.
     // 17. Set the attributes of the length own property of F to the values
     //   specified in 15.3.5.1.
 
     // TODO
     // 18. Set the [[Extensible]] internal property of F to true.
 
     // TODO
     // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
     // 20. Call the [[DefineOwnProperty]] internal method of F with
     //   arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
     //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
     //   false.
     // 21. Call the [[DefineOwnProperty]] internal method of F with
     //   arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
     //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
     //   and false.
 
     // TODO
     // NOTE Function objects created using Function.prototype.bind do not
     // have a prototype property or the [[Code]], [[FormalParameters]], and
     // [[Scope]] internal properties.
     // XXX can't delete prototype in pure-js.
 
     // 22. Return F.
     return bound;
 };
}
 
//Shortcut to an often accessed properties, in order to avoid multiple
//dereference that costs universally.
//_Please note: Shortcuts are defined after `Function.prototype.bind` as we
//us it in defining shortcuts.
var call = Function.prototype.call;
var prototypeOfArray = Array.prototype;
var prototypeOfObject = Object.prototype;
var slice = prototypeOfArray.slice;
//Having a toString local variable name breaks in Opera so use _toString.
var _toString = call.bind(prototypeOfObject.toString);
var owns = call.bind(prototypeOfObject.hasOwnProperty);
 
//If JS engine supports accessors creating shortcuts.
var defineGetter;
var defineSetter;
var lookupGetter;
var lookupSetter;
var supportsAccessors;
if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
 defineGetter = call.bind(prototypeOfObject.__defineGetter__);
 defineSetter = call.bind(prototypeOfObject.__defineSetter__);
 lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
 lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
}
 
//
//Array
//=====
//
 
//ES5 15.4.4.12
//http://es5.github.com/#x15.4.4.12
//Default value for second param
//[bugfix, ielt9, old browsers]
//IE < 9 bug: [1,2].splice(0).join("") == "" but should be "12"
if ([1,2].splice(0).length != 2) {
 var array_splice = Array.prototype.splice;
 Array.prototype.splice = function(start, deleteCount) {
     if (!arguments.length) {
         return [];
     } else {
         return array_splice.apply(this, [
             start === void 0 ? 0 : start,
             deleteCount === void 0 ? (this.length - start) : deleteCount
         ].concat(slice.call(arguments, 2)))
     }
 };
}
 
//ES5 15.4.4.12
//http://es5.github.com/#x15.4.4.13
//Return len+argCount.
//[bugfix, ielt8]
//IE < 8 bug: [].unshift(0) == undefined but should be "1"
if ([].unshift(0) != 1) {
 var array_unshift = Array.prototype.unshift;
 Array.prototype.unshift = function() {
     array_unshift.apply(this, arguments);
     return this.length;
 };
}
 
//ES5 15.4.3.2
//http://es5.github.com/#x15.4.3.2
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray) {
 Array.isArray = function isArray(obj) {
     return _toString(obj) == "[object Array]";
 };
}
 
//The IsCallable() check in the Array functions
//has been replaced with a strict check on the
//internal class of the object to trap cases where
//the provided function was actually a regular
//expression literal, which in V8 and
//JavaScriptCore is a typeof "function".  Only in
//V8 are regular expression literals permitted as
//reduce parameters, so it is desirable in the
//general case for the shim to match the more
//strict and common behavior of rejecting regular
//expressions.
 
//ES5 15.4.4.18
//http://es5.github.com/#x15.4.4.18
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
 
//Check failure of by-index access of string characters (IE < 9)
//and failure of `0 in boxedString` (Rhino)
var boxedString = Object("a"),
 splitString = boxedString[0] != "a" || !(0 in boxedString);
 
if (!Array.prototype.forEach) {
 Array.prototype.forEach = function forEach(fun /*, thisp*/) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         thisp = arguments[1],
         i = -1,
         length = self.length >>> 0;
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(); // TODO message
     }
 
     while (++i < length) {
         if (i in self) {
             // Invoke the callback function with call, passing arguments:
             // context, property value, property key, thisArg object
             // context
             fun.call(thisp, self[i], i, object);
         }
     }
 };
}
 
//ES5 15.4.4.19
//http://es5.github.com/#x15.4.4.19
//https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map) {
 Array.prototype.map = function map(fun /*, thisp*/) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         length = self.length >>> 0,
         result = Array(length),
         thisp = arguments[1];
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     for (var i = 0; i < length; i++) {
         if (i in self)
             result[i] = fun.call(thisp, self[i], i, object);
     }
     return result;
 };
}
 
//ES5 15.4.4.20
//http://es5.github.com/#x15.4.4.20
//https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
if (!Array.prototype.filter) {
 Array.prototype.filter = function filter(fun /*, thisp */) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
                 object,
         length = self.length >>> 0,
         result = [],
         value,
         thisp = arguments[1];
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     for (var i = 0; i < length; i++) {
         if (i in self) {
             value = self[i];
             if (fun.call(thisp, value, i, object)) {
                 result.push(value);
             }
         }
     }
     return result;
 };
}
 
//ES5 15.4.4.16
//http://es5.github.com/#x15.4.4.16
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
if (!Array.prototype.every) {
 Array.prototype.every = function every(fun /*, thisp */) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         length = self.length >>> 0,
         thisp = arguments[1];
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     for (var i = 0; i < length; i++) {
         if (i in self && !fun.call(thisp, self[i], i, object)) {
             return false;
         }
     }
     return true;
 };
}
 
//ES5 15.4.4.17
//http://es5.github.com/#x15.4.4.17
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
if (!Array.prototype.some) {
 Array.prototype.some = function some(fun /*, thisp */) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         length = self.length >>> 0,
         thisp = arguments[1];
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     for (var i = 0; i < length; i++) {
         if (i in self && fun.call(thisp, self[i], i, object)) {
             return true;
         }
     }
     return false;
 };
}
 
//ES5 15.4.4.21
//http://es5.github.com/#x15.4.4.21
//https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
if (!Array.prototype.reduce) {
 Array.prototype.reduce = function reduce(fun /*, initial*/) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         length = self.length >>> 0;
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     // no value to return if no initial value and an empty array
     if (!length && arguments.length == 1) {
         throw new TypeError("reduce of empty array with no initial value");
     }
 
     var i = 0;
     var result;
     if (arguments.length >= 2) {
         result = arguments[1];
     } else {
         do {
             if (i in self) {
                 result = self[i++];
                 break;
             }
 
             // if array contains no values, no initial value to return
             if (++i >= length) {
                 throw new TypeError("reduce of empty array with no initial value");
             }
         } while (true);
     }
 
     for (; i < length; i++) {
         if (i in self) {
             result = fun.call(void 0, result, self[i], i, object);
         }
     }
 
     return result;
 };
}
 
//ES5 15.4.4.22
//http://es5.github.com/#x15.4.4.22
//https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
if (!Array.prototype.reduceRight) {
 Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
     var object = toObject(this),
         self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             object,
         length = self.length >>> 0;
 
     // If no callback function or if callback is not a callable function
     if (_toString(fun) != "[object Function]") {
         throw new TypeError(fun + " is not a function");
     }
 
     // no value to return if no initial value, empty array
     if (!length && arguments.length == 1) {
         throw new TypeError("reduceRight of empty array with no initial value");
     }
 
     var result, i = length - 1;
     if (arguments.length >= 2) {
         result = arguments[1];
     } else {
         do {
             if (i in self) {
                 result = self[i--];
                 break;
             }
 
             // if array contains no values, no initial value to return
             if (--i < 0) {
                 throw new TypeError("reduceRight of empty array with no initial value");
             }
         } while (true);
     }
 
     do {
         if (i in this) {
             result = fun.call(void 0, result, self[i], i, object);
         }
     } while (i--);
 
     return result;
 };
}
 
//ES5 15.4.4.14
//http://es5.github.com/#x15.4.4.14
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
 Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
     var self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             toObject(this),
         length = self.length >>> 0;
 
     if (!length) {
         return -1;
     }
 
     var i = 0;
     if (arguments.length > 1) {
         i = toInteger(arguments[1]);
     }
 
     // handle negative indices
     i = i >= 0 ? i : Math.max(0, length + i);
     for (; i < length; i++) {
         if (i in self && self[i] === sought) {
             return i;
         }
     }
     return -1;
 };
}
 
//ES5 15.4.4.15
//http://es5.github.com/#x15.4.4.15
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
 Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
     var self = splitString && _toString(this) == "[object String]" ?
             this.split("") :
             toObject(this),
         length = self.length >>> 0;
 
     if (!length) {
         return -1;
     }
     var i = length - 1;
     if (arguments.length > 1) {
         i = Math.min(i, toInteger(arguments[1]));
     }
     // handle negative indices
     i = i >= 0 ? i : length - Math.abs(i);
     for (; i >= 0; i--) {
         if (i in self && sought === self[i]) {
             return i;
         }
     }
     return -1;
 };
}
 
//
//Object
//======
//
 
//ES5 15.2.3.14
//http://es5.github.com/#x15.2.3.14
if (!Object.keys) {
 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
 var hasDontEnumBug = true,
     dontEnums = [
         "toString",
         "toLocaleString",
         "valueOf",
         "hasOwnProperty",
         "isPrototypeOf",
         "propertyIsEnumerable",
         "constructor"
     ],
     dontEnumsLength = dontEnums.length;
 
 for (var key in {"toString": null}) {
     hasDontEnumBug = false;
 }
 
 Object.keys = function keys(object) {
 
     if (
         (typeof object != "object" && typeof object != "function") ||
         object === null
     ) {
         throw new TypeError("Object.keys called on a non-object");
     }
 
     var keys = [];
     for (var name in object) {
         if (owns(object, name)) {
             keys.push(name);
         }
     }
 
     if (hasDontEnumBug) {
         for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
             var dontEnum = dontEnums[i];
             if (owns(object, dontEnum)) {
                 keys.push(dontEnum);
             }
         }
     }
     return keys;
 };
 
}
 
//
//Date
//====
//
 
//ES5 15.9.5.43
//http://es5.github.com/#x15.9.5.43
//This function returns a String value represent the instance in time
//represented by this Date object. The format of the String is the Date Time
//string format defined in 15.9.1.15. All fields are present in the String.
//The time zone is always UTC, denoted by the suffix Z. If the time value of
//this object is not a finite Number a RangeError exception is thrown.
var negativeDate = -62198755200000,
 negativeYearString = "-000001";
if (
 !Date.prototype.toISOString ||
 (new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1)
) {
 Date.prototype.toISOString = function toISOString() {
     var result, length, value, year, month;
     if (!isFinite(this)) {
         throw new RangeError("Date.prototype.toISOString called on non-finite value.");
     }
 
     year = this.getUTCFullYear();
 
     month = this.getUTCMonth();
     // see https://github.com/kriskowal/es5-shim/issues/111
     year += Math.floor(month / 12);
     month = (month % 12 + 12) % 12;
 
     // the date time string format is specified in 15.9.1.15.
     result = [month + 1, this.getUTCDate(),
         this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
     year = (
         (year < 0 ? "-" : (year > 9999 ? "+" : "")) +
         ("00000" + Math.abs(year))
         .slice(0 <= year && year <= 9999 ? -4 : -6)
     );
 
     length = result.length;
     while (length--) {
         value = result[length];
         // pad months, days, hours, minutes, and seconds to have two
         // digits.
         if (value < 10) {
             result[length] = "0" + value;
         }
     }
     // pad milliseconds to have three digits.
     return (
         year + "-" + result.slice(0, 2).join("-") +
         "T" + result.slice(2).join(":") + "." +
         ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"
     );
 };
}
 
 
//ES5 15.9.5.44
//http://es5.github.com/#x15.9.5.44
//This function provides a String representation of a Date object for use by
//JSON.stringify (15.12.3).
var dateToJSONIsSupported = false;
try {
 dateToJSONIsSupported = (
     Date.prototype.toJSON &&
     new Date(NaN).toJSON() === null &&
     new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
     Date.prototype.toJSON.call({ // generic
         toISOString: function () {
             return true;
         }
     })
 );
} catch (e) {
}
if (!dateToJSONIsSupported) {
 Date.prototype.toJSON = function toJSON(key) {
     // When the toJSON method is called with argument key, the following
     // steps are taken:
 
     // 1.  Let O be the result of calling ToObject, giving it the this
     // value as its argument.
     // 2. Let tv be toPrimitive(O, hint Number).
     var o = Object(this),
         tv = toPrimitive(o),
         toISO;
     // 3. If tv is a Number and is not finite, return null.
     if (typeof tv === "number" && !isFinite(tv)) {
         return null;
     }
     // 4. Let toISO be the result of calling the [[Get]] internal method of
     // O with argument "toISOString".
     toISO = o.toISOString;
     // 5. If IsCallable(toISO) is false, throw a TypeError exception.
     if (typeof toISO != "function") {
         throw new TypeError("toISOString property is not callable");
     }
     // 6. Return the result of calling the [[Call]] internal method of
     //  toISO with O as the this value and an empty argument list.
     return toISO.call(o);
 
     // NOTE 1 The argument is ignored.
 
     // NOTE 2 The toJSON function is intentionally generic; it does not
     // require that its this value be a Date object. Therefore, it can be
     // transferred to other kinds of objects for use as a method. However,
     // it does require that any such object have a toISOString method. An
     // object is free to use the argument key to filter its
     // stringification.
 };
}
 
//ES5 15.9.4.2
//http://es5.github.com/#x15.9.4.2
//based on work shared by Daniel Friesen (dantman)
//http://gist.github.com/303249
if (!Date.parse || "Date.parse is buggy") {
 // XXX global assignment won't work in embeddings that use
 // an alternate object for the context.
 Date = (function(NativeDate) {
 
     // Date.length === 7
     function Date(Y, M, D, h, m, s, ms) {
         var length = arguments.length;
         if (this instanceof NativeDate) {
             var date = length == 1 && String(Y) === Y ? // isString(Y)
                 // We explicitly pass it through parse:
                 new NativeDate(Date.parse(Y)) :
                 // We have to manually make calls depending on argument
                 // length here
                 length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
                 length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
                 length >= 5 ? new NativeDate(Y, M, D, h, m) :
                 length >= 4 ? new NativeDate(Y, M, D, h) :
                 length >= 3 ? new NativeDate(Y, M, D) :
                 length >= 2 ? new NativeDate(Y, M) :
                 length >= 1 ? new NativeDate(Y) :
                               new NativeDate();
             // Prevent mixups with unfixed Date object
             date.constructor = Date;
             return date;
         }
         return NativeDate.apply(this, arguments);
     };
 
     // 15.9.1.15 Date Time String Format.
     var isoDateExpression = new RegExp("^" +
         "(\d{4}|[+-]\d{6})" + // four-digit year capture or sign +
                                   // 6-digit extended year
         "(?:-(\d{2})" + // optional month capture
         "(?:-(\d{2})" + // optional day capture
         "(?:" + // capture hours:minutes:seconds.milliseconds
             "T(\d{2})" + // hours capture
             ":(\d{2})" + // minutes capture
             "(?:" + // optional :seconds.milliseconds
                 ":(\d{2})" + // seconds capture
                 "(?:\.(\d{3}))?" + // milliseconds capture
             ")?" +
         "(" + // capture UTC offset component
             "Z|" + // UTC capture
             "(?:" + // offset specifier +/-hours:minutes
                 "([-+])" + // sign capture
                 "(\d{2})" + // hours offset capture
                 ":(\d{2})" + // minutes offset capture
             ")" +
         ")?)?)?)?" +
     "$");
 
     var months = [
         0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
     ];
 
     function dayFromMonth(year, month) {
         var t = month > 1 ? 1 : 0;
         return (
             months[month] +
             Math.floor((year - 1969 + t) / 4) -
             Math.floor((year - 1901 + t) / 100) +
             Math.floor((year - 1601 + t) / 400) +
             365 * (year - 1970)
         );
     }
 
     // Copy any custom methods a 3rd party library may have added
     for (var key in NativeDate) {
         Date[key] = NativeDate[key];
     }
 
     // Copy "native" methods explicitly; they may be non-enumerable
     Date.now = NativeDate.now;
     Date.UTC = NativeDate.UTC;
     Date.prototype = NativeDate.prototype;
     Date.prototype.constructor = Date;
 
     // Upgrade Date.parse to handle simplified ISO 8601 strings
     Date.parse = function parse(string) {
         var match = isoDateExpression.exec(string);
         if (match) {
             // parse months, days, hours, minutes, seconds, and milliseconds
             // provide default values if necessary
             // parse the UTC offset component
             var year = Number(match[1]),
                 month = Number(match[2] || 1) - 1,
                 day = Number(match[3] || 1) - 1,
                 hour = Number(match[4] || 0),
                 minute = Number(match[5] || 0),
                 second = Number(match[6] || 0),
                 millisecond = Number(match[7] || 0),
                 // When time zone is missed, local offset should be used
                 // (ES 5.1 bug)
                 // see https://bugs.ecmascript.org/show_bug.cgi?id=112
                 offset = !match[4] || match[8] ?
                     0 : Number(new NativeDate(1970, 0)),
                 signOffset = match[9] === "-" ? 1 : -1,
                 hourOffset = Number(match[10] || 0),
                 minuteOffset = Number(match[11] || 0),
                 result;
             if (
                 hour < (
                     minute > 0 || second > 0 || millisecond > 0 ?
                     24 : 25
                 ) &&
                 minute < 60 && second < 60 && millisecond < 1000 &&
                 month > -1 && month < 12 && hourOffset < 24 &&
                 minuteOffset < 60 && // detect invalid offsets
                 day > -1 &&
                 day < (
                     dayFromMonth(year, month + 1) -
                     dayFromMonth(year, month)
                 )
             ) {
                 result = (
                     (dayFromMonth(year, month) + day) * 24 +
                     hour +
                     hourOffset * signOffset
                 ) * 60;
                 result = (
                     (result + minute + minuteOffset * signOffset) * 60 +
                     second
                 ) * 1000 + millisecond + offset;
                 if (-8.64e15 <= result && result <= 8.64e15) {
                     return result;
                 }
             }
             return NaN;
         }
         return NativeDate.parse.apply(this, arguments);
     };
 
     return Date;
 })(Date);
}
 
//ES5 15.9.4.4
//http://es5.github.com/#x15.9.4.4
if (!Date.now) {
 Date.now = function now() {
     return new Date().getTime();
 };
}
 
 
//
//String
//======
//
 
 
//ES5 15.5.4.14
//http://es5.github.com/#x15.5.4.14
//[bugfix, chrome]
//If separator is undefined, then the result array contains just one String,
//which is the this value (converted to a String). If limit is not undefined,
//then the output array is truncated so that it contains no more than limit
//elements.
//"0".split(undefined, 0) -> []
if("0".split(void 0, 0).length) {
 var string_split = String.prototype.split;
 String.prototype.split = function(separator, limit) {
     if(separator === void 0 && limit === 0)return [];
     return string_split.apply(this, arguments);
 }
}
 
//ECMA-262, 3rd B.2.3
//Note an ECMAScript standart, although ECMAScript 3rd Edition has a
//non-normative section suggesting uniform semantics and it should be
//normalized across all browsers
//[bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
if("".substr && "0b".substr(-1) !== "b") {
 var string_substr = String.prototype.substr;
 /**
  *  Get the substring of a string
  *  @param  {integer}  start   where to start the substring
  *  @param  {integer}  length  how many characters to return
  *  @return {string}
  */
 String.prototype.substr = function(start, length) {
     return string_substr.call(
         this,
         start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,
         length
     );
 }
}
 
//ES5 15.5.4.20
//http://es5.github.com/#x15.5.4.20
var ws = "x09x0Ax0Bx0Cx0Dx20xA0u1680u180Eu2000u2001u2002u2003" +
 "u2004u2005u2006u2007u2008u2009u200Au202Fu205Fu3000u2028" +
 "u2029uFEFF";
if (!String.prototype.trim || ws.trim()) {
 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
 // http://perfectionkills.com/whitespace-deviations/
 ws = "[" + ws + "]";
 var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
     trimEndRegexp = new RegExp(ws + ws + "*$");
 String.prototype.trim = function trim() {
     if (this === undefined || this === null) {
         throw new TypeError("can't convert "+this+" to object");
     }
     return String(this)
         .replace(trimBeginRegexp, "")
         .replace(trimEndRegexp, "");
 };
}
 
//
//Util
//======
//
 
//ES5 9.4
//http://es5.github.com/#x9.4
//http://jsperf.com/to-integer
 
function toInteger(n) {
 n = +n;
 if (n !== n) { // isNaN
     n = 0;
 } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
     n = (n > 0 || -1) * Math.floor(Math.abs(n));
 }
 return n;
}
 
function isPrimitive(input) {
 var type = typeof input;
 return (
     input === null ||
     type === "undefined" ||
     type === "boolean" ||
     type === "number" ||
     type === "string"
 );
}
 
function toPrimitive(input) {
 var val, valueOf, toString;
 if (isPrimitive(input)) {
     return input;
 }
 valueOf = input.valueOf;
 if (typeof valueOf === "function") {
     val = valueOf.call(input);
     if (isPrimitive(val)) {
         return val;
     }
 }
 toString = input.toString;
 if (typeof toString === "function") {
     val = toString.call(input);
     if (isPrimitive(val)) {
         return val;
     }
 }
 throw new TypeError();
}
 
//ES5 9.9
//http://es5.github.com/#x9.9
var toObject = function (o) {
 if (o == null) { // this matches both null and undefined
     throw new TypeError("can't convert "+o+" to object");
 }
 return Object(o);
};
 
});

有了这个库,尽管你的浏览器还没支持ECMAScript5,也可以使用它的API了,提前学会用新的ECMAScript5函数。

代码来自:https://github.com/kriskowal/es5-shim

请转载遵守相关协议。

posted @ 2013-01-14 21:41  水之原  阅读(4253)  评论(0编辑  收藏  举报