Skip to content

Instantly share code, notes, and snippets.

@yuku
Created November 14, 2011 18:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuku/1364652 to your computer and use it in GitHub Desktop.
Save yuku/1364652 to your computer and use it in GitHub Desktop.
ECMAScript 5
// 8.6.2 Object Internal Properties and Methods
// Evenry ECMAScript object has a Boolean-valued [[Extensible]] internal
// property that controls whether or not named properties may be added to the
// object. If the value of the [[Extensible]] internal property is false then
// additional named properties may not be added to the object. In addition, if
// [[Extensible]] is false the value of the [[Class]] and [[Prototype]]
// internal properties of the object may not be modified. Once the value of an
// [[Extensible]] internal property has been set to false it may not be
// subsequently changed to true.
Object.defineProperty(Object.prototype, 'Extensible', {
value: true, writable: false, enumerable: false, configurable:false
});
// 8.10.1 IsAccessorDescriptor(Desc)
var IsAccessorDescriptor = function(Desc) {
// 1. If Desc is undefined, then return false.
if (Desc === undefined) {
return false;
}
// 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, then return false.
if (Desc.set === undefined && Desc.get === undefined) {
return false;
}
// 3. Return true.
return true;
};
// 8.10.2 IsDataDescriptor(Desc)
var IsDataDescriptor = function(Desc) {
// 1. If Desc is undefined, then return false.
if (Desc === undefined) {
return false;
}
// 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, then return
// false.
if (Desc.value === undefined && Desc.writable === undefined) {
return false;
}
// 3. Return true.
return true;
};
// 8.10.3 IsGenericDescriptor(Desc)
var IsGenericDescriptor = function(Desc) {
// 1. If Desc is undefined, then return false.
if (Desc === undefined) {
return false;
}
// 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both
// false, then return true.
if (!IsAccessorDescriptor(Desc) && !IsDataDescriptor(Desc)) {
return true;
}
// 3. Return false.
return false;
};
// 8.10.4 FromPropertyDescriptor(Desc)
var FromPropertyDescriptor = function(Desc) {
// The following algorithm assumes that Desc is a fully populated Property
// Descriptor, such as that returned from [[GetOwnProperty]] (see 8.12.1).
// 1. If Desc is undefined, then return undefined.
if (Desc === undefined) {
return undefined;
}
// 2. Let obj be the result of creating a new object as if by the expression
// new Object() where Object is the standard built-in constructor with
// that name.
var obj = new Object();
// 3. If IsDataDescriptor(Desc) is true, then
if (IsDataDescriptor(Desc)) {
// a. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "value", Property Descriptor {[[Value]]: Desc.[[Value]], [[Writable]]:
// true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
obj.DefineOwnProperty("value", {
value: Desc.value,
writable: true,
enumerable: true,
configurable: true
}, false);
// b. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "writable", Property Descriptor {[[Value]]: Desc.[[Writable]],
// [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true},
// and false.
obj.DefineOwnProperty("writable", {
value: Desc.writable,
writable: true,
enumerable: true,
configurable: true
}, false);
}
// 4. Else, IsAccessorDescriptor(Desc) must be true, so
else {
// a. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "get", Property Descriptor {[[Value]]: Desc.[[Get]], [[Writable]]:
// true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
obj.DefineOwnProperty("get", {
value: Desc.get,
writable: true,
enumerable: true,
configurable: true
}, false);
// b. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "set", Property Descriptor {[[Value]]: Desc.[[Set]], [[Writable]]:
// true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
obj.DefineOwnProperty("set", {
value: Desc.set,
writable: true,
enumerable: true,
configurable: true
}, false);
}
// 5. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "enumerable", Property Descriptor {[[Value]]: Desc.[[Enumerable]],
// [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and
// false.
obj.DefineOwnProperty("enumerable", {
value: Desc.enumerable,
writable: true,
enumerable: true,
configurable: true
}, false);
// 6. Call the [[DefineOwnProperty]] internal method of obj with arguments
// "configurable", Property Descriptor {[[Value]]: Desc.[[Configurable]],
// [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and
// false.
obj.DefineOwnProperty("configurable", {
value: Desc.configurable,
writable: true,
enumerable: true,
configurable: true
}, false);
// 7. Return obj.
return obj;
};
// 8.10.5 ToPropertyDescriptor(Obj)
var ToPropertyDescriptor = function(Obj) {
// 1. If Type(Obj) is not Object throw a TypeError exception.
if (typeof O !== "object") {
throw TypeError;
}
// 2. Let desc be the result of creating a new Property Descriptor that
// initially has no fields.
var desc = {};
// 3. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "enumerable" is true, then
if (O.HasProperty("enumerable")) {
// a. Let enum be the result of calling the [[Get]] internal method of Obj
// with "enumerable".
var enum = Obj.Get("enumerable");
// b. Set the [[Enumerable]] field of desc to ToBoolean(enum).
desc.enumerable = ToBoolean(enum);
}
// 4. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "configurable" is true, then
if (O.HasProperty("configurable")) {
// a. Let conf be the result of calling the [[Get]] internal method of Obj
// with argument "configurable".
var conf = Obj.Get("configurable");
// b. Set the [[Configurable]] field of desc to ToBoolean(conf).
desc.configurable = ToBoolean(conf);
}
// 5. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "value" is true, then
if (O.HasProperty("value")) {
// a. Let value be the result of calling the [[Get]] internal method of Obj
// with argument “value”.
var value = Obj.Get("value");
// b. Set the [[Value]] field of desc to value.
desc.value = value;
}
// 6. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "writable" is true, then
if (O.HasProperty("writable")) {
// a. Let writable be the result of calling the [[Get]] internal method of
// Obj with argument "writable".
var writable = Obj.Get("writable");
// b. Set the [[Writable]] field of desc to ToBoolean(writable).
desc.writable = ToBoolean(writable);
}
// 7. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "get" is true, then
if (O.HasProperty("get")) {
// a. Let getter be the result of calling the [[Get]] internal method of
// Obj with argument "get".
var getter = Obj.Get("get");
// b. If IsCallable(getter) is false and getter is not undefined, then
// throw a TypeError exception.
if (!IsCallable(getter) && getter !== undefined) {
throw TypeError;
}
// c. Set the [[Get]] field of desc to getter.
desc.get = getter;
}
// 8. If the result of calling the [[HasProperty]] internal method of Obj
// with argument "set" is true, then
if (O.HasProperty("set")) {
// a. Let setter be the result of calling the [[Get]] internal method of
// Obj with argument "set".
var setter = Obj.Get("set");
// b. If IsCallable(setter) is false and setter is not undefined, then
// throw a TypeError exception.
if (!IsCallable(setter) && setter !== undefined) {
throw TypeError;
}
// c. Set the [[Set]] field of desc to setter.
desc.set = setter;
}
// 9. If either desc.[[Get]] or desc.[[Set]] are present, then
if (desc.get || desc.set) {
// a. If either desc.[[Value]] or desc.[[Writable]] are present, then throw
// a TypeError exception.
if (desc.value || desc.writable) {
throw TypeError;
}
}
// 10. Return desc.
return desc;
};
// 8.12.1 [[GetOwnProperty]](P)
Object.prototype.GetOwnProperty = function(P) {
var O = this
// 1. If O doesn't have an own property with name P, return undefined.
if (O[P] === undefined) return undefined;
// 2. Let D be a newly created Property Descriptor with no fields.
var D = {};
// 3. Let X be O's own property named P.
var X = ToPropertyDescriptor(O[P]);
// 4. If X is a data property, then
if (IsDataDescriptor(X)) {
// a. Set D.[[Value]] to the value of X's [[Value]] attribute.
D.value = X.value;
// b. Set D.[[Writable]] to the value of X's [[Writable]] attribute.
D.writable = X.writable;
}
// 5. Else X is an accessor property, so
else {
// a.Set D.[[Get]] to the value of X's [[Get]] attribute.
D.get = X.get;
// b.Set D.[[Set]] to the value of X's [[Set]] attribute.
D.set = X.set;
}
// 6. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
D.enumerable = X.enumerable;
// 7. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
D.configurable = X.configurable;
// 8. Return D.
return D;
};
// 8.12.2 [[GetProperty]](P)
Object.prototype.GetProperty = function(P) {
var O = this;
// 1. Let prop be the result of calling the [[GetOwnProperty]] internal
// method of O with property name P.
var prop = O.GetOwnProperty(P);
// 2. If prop is not undefined, return prop.
if (prop !== undefined) {
return prop;
}
// 3. Let proto be the value of the [[Prototype]] internal property of O.
var proto = O.__proto__;
// 4. If proto is null, return undefined.
if (proto === null) {
return undefined;
}
// 5. Return the result of calling the [[GetProperty]] internal method of
// proto with argument P.
return proto.GetProperty(P);
}
// 8.12.3 [[Get]](P)
Object.prototype.Get = function (P) {
var O = this;
// 1. Let desc be the result of calling the [[GetProperty]] internal method
// of O with property name P.
var desc = O.GetProperty(P);
// 2. If desc is undefined, return undefined.
if (desc === undefined) {
return undefined;
}
// 3. If IsDataDescriptor(desc) is true, return desc.[[Value]].
if (IsDataDescriptor(desc)) {
return desc.value;
}
// 4. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be
// desc.[[Get]].
var getter = desc.get;
// 5. If getter is undefined, return undefined.
if (getter === undefined) {
return undefined;
}
// 6. Return the result calling the [[Call]] internal method of getter
// providing O as the this value and providing no arguments.
return getter.call(O);
};
// 8.12.4 [[CanPut]](P)
Object.prototype.CanPut = function(P) {
// 1. Let desc be the result of calling the [[GetOwnProperty]] internal
// method of O with argument P.
var desc = O.GetOwnProperty(P);
// 2. If desc is not undefined, then
if (desc !== undefined) {
// a. If IsAccessorDescriptor(desc) is true, then
if (IsAccessorDescriptor(desc)) {
// i. If desc.[[Set]] is undefined, then return false.
if (desc.set === undefined) {
return false;
}
// ii. Else return true.
else {
return true;
}
}
// b. Else, desc must be a DataDescriptor so return the value of
// desc.[[Writable]].
else {
return desc.writable;
}
}
// 3. Let proto be the [[Prototype]] internal property of O.
var proto = O.__proto__;
// 4. If proto is null, then return the value of the [[Extensible]] internal
// property of O.
if (proto === null) {
return proto.Extensible;
}
// 5. Let inherited be the result of calling the [[GetProperty]] internal
// method of proto with property name P.
var inherited = proto.GetProperty(P);
// 6. If inherited is undefined, return the value of the [[Extensible]]
// internal property of O.
if (inherited === undefined) {
return O.Extensible;
}
// 7. If IsAccessorDescriptor(inherited) is true, then
if (IsAccessorDescriptor(inherited)) {
// a. If inherited.[[Set]] is undefined, then return false.
if (inherited.set === undefined) {
return false;
}
// b. Else return true.
else {
return true;
}
}
// 8. Else, inherited must be a DataDescriptor
else {
// a. If the [[Extensible]] internal property of O is false, return false.
if (O.Extensible === false) {
return false;
}
// b. Else return the value of inherited.[[Writable]].
else {
return inherited.writable;
}
}
};
// 8.12.5 [[Put]](P, V, Throw)
Object.prototype.Put = function(P, V, Throw) {
};
// 8.12.6 [[HasProperty]](P)
Object.prototype.HasProperty = function(P) {
var O = this;
// 1. Let desc be the result of calling the [[GetProperty]] internal method
// of O with property name P.
var desc = O.GetProperty(P);
// 2. If desc is undefined, then return false.
if (desc === undefined) {
return false;
}
// 3. Else return true.
else {
return true;
}
};
// 9.2 ToBoolean
var ToBoolean = function(arg) {
// ToBoolean Conversions
// +-------------+-------------------------------------------------------+
// |Argument Type|Result |
// +=============+=======================================================+
// |Undefined |false |
// +-------------+-------------------------------------------------------+
// |Null |false |
// +-------------+-------------------------------------------------------+
// |Boolean |The result equals the input argument (no conversion). |
// +-------------+-------------------------------------------------------+
// |Number |The result is false if the argument is +0, -0, or NaN; |
// | |otherwise thr result is true. |
// +-------------+-------------------------------------------------------+
// |String |The result is false if the argument is the empty String|
// | |(its length is zero); otherwise the result is true. |
// +-------------+-------------------------------------------------------+
// |Object |true |
// +-------------+-------------------------------------------------------+
if (arg == null) {
return false
}
switch (typeof arg) {
case "boolean":
return arg;
case "number":
return arg !== 0 && !isNaN(arg);
case "string":
return arg.length !== 0;
case "object":
return true;
}
};
// 9.11 IsCallable
var IsCallable = function(arg) {
// IsCallable Results
// +-------------+-------------------------------------------------------+
// |Argument Type|Result |
// +=============+=======================================================+
// |Undefined |Return false. |
// +-------------+-------------------------------------------------------+
// |Null |Return false. |
// +-------------+-------------------------------------------------------+
// |Boolean |Return false. |
// +-------------+-------------------------------------------------------+
// |Number |Return false. |
// +-------------+-------------------------------------------------------+
// |String |Return false. |
// +-------------+-------------------------------------------------------+
// |Object |If the argument object has a [[Call]] internal method, |
// | |then return true, otherwise return false. |
// +-------------+-------------------------------------------------------+
if (typeof arg !== "object") {
return false;
}
return typeof arg.call === "function";
};
// 15.2.3.2 Object.getPrototypeOf(O)
Object.getPrototypeOf = function (O) {
// 1. If Type(O) is not Object, throw a TypeError exception.
if (typeof O !== "object") {
throw TypeError("Object.getPrototypeOf called on non-object");
}
// 2. Return the value of the [[Prototype]] internal property of O
return O.__proto__;
};
// 15.2.3.3 Object.getOwnPropertyDescriptor(O, P)
Object.getOwnPropertyDescriptor = function(O, P) {
// 1. If Type(O) is not Object throw a TypeError exception.
if (typeof O !== "object") {
throw TypeError("Object.getOwnPropertyDescriptor called on non-object");
}
// 2. Let name be ToString(P).
var name = P.toString();
// 3. Let desc be the result of calling the [[GetOwnProperty]] internal
// method of O with argument name.
var desc = O.GetOwnProperty(name);
// 4. Return the result of calling FromPropertyDescriptor(desc) (8.10.4).
return FromPropertyDescriptor(desc);
};
// 15.2.3.5 Object.create(O[, Properties])
//
// The create function creates a new object with a specifed prototype.
Object.create = function (O, Properties) {
// 1. If Type(O) is not Object or Null, throw a TypeError exception.
if (typeof O !== "object" || O === null) {
throw TypeError("Object prototype may only be an Object or null");
}
// 2. Let obj be the result of creating a new object as if by the expression
// new Object() where Object is the standard built-in constructor with
// that name.
var obj = new Object();
// 3. Set the [[Prototype]] internal property of obj to O
obj.__proto__ = O;
// 4. If the argument Properties is present and not undefined, add own
// properties to obj as if by calling the standard built-in function
// Object.defineProperties with arguments obj and Properties.
if (Properties !== undefined) {
Object.defineProperties(obj, Properties);
}
// 5. Return obj.
return obj
};
// 15.2.3.14 Object.keys(O)
Object.keys = function (O) {
if (typeof O !== "object") {
throw TypeError("Object.keys called on non-object");
}
var array = [], index = 0;
for (var P in O) {
if (O.hasOwnProperty(P)) {
Object.defineProperty(array, index, {
value: P, writable: true, enumerable: true, configurable: true
});
index++;
}
}
return array;
};
// 15.2.4.6 Object.prototype.isPrototypeOf(V)
Object.prototype.isPrototypeOf = function (V) {
if (typeof V !== "object") { return false }
while (V = Object.getPrototypeOf(V)) {
if (V === null) {
return false
} else if (this === V) {
return true
}
}
};
// 15.4.3.2 Array.isArray(arg)
Array.isArray = function (arg) {
return arg.constructor.name === "Array"
};
// 15.4.4.14 Array.prototype.indexOf(searchElement[, fromIndex])
Array.prototype.indexOf = function (searchElement, fromIndex) {
if (this.length == 0) { return -1 }
fromIndex = 0 + fromIndex || 0;
if (fromIndex >= this.length) { return -1 }
var k;
if (fromIndex >= 0) {
k = fromIndex;
} else {
k = Math.max(len - Math.abs(fromIndex), 0);
}
for (; k < this.length; k++) {
if (this[k] === searchElement) {
return k
}
}
}
return -1
};
// 15.4.4.15 Array.prototype.lastIndexOf(searchElement[, fromIndex])
Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
if (this.length == 0) { return -1 }
fromIndex = 0 + fromIndex || this.len - 1;
var k;
if (fromIndex >= 0) {
k = Math.min(fromIndex, this.length - 1);
} else {
k = this.length - Math.abs(fromIndex);
}
for (; k >= 0; k--) {
if (this[k] === searchElement) {
return k
}
}
return -1
};
// 15.4.4.16 Array.prototype.every(callbackfn[, thisArg])
Array.prototype.every = function (callbackfn, thisArg) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
}
for (var k = 0; k < this.length; k++) {
if (!callbackfn.call(thisArg, this[k])) {
return false;
}
}
return true;
};
// 15.4.4.17 Array.prototype.some(callbackfn[, thisArg])
Array.prototype.some = function (callbackfn, thisArg) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
}
for (var k = 0; k < this.length; k++) {
if (callbackfn.call(thisArg, this[k])) {
return true;
}
}
return false;
};
// 15.4.4.18 Array.prototype.forEach(callbackfn[, thisArg])
Array.prototype.forEach = function (callbackfn, thisArg) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
}
for (var k = 0; k < this.length; k++) {
callbackfn.call(thisArg, this[k]);
}
};
// 15.4.4.19 Array.prototype.map(callbackfn[, thisArg])
Array.prototype.map = function (callbackfn, thisArg) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
}
var a = [];
for (var k = 0; k < this.length; k++) {
a.push(callbackfn.call(thisArg, this[k]));
}
return a;
};
// 15.4.4.20 Array.prototype.filter(callbackfn[, thisArg])
Array.prototype.filter = function (callbackfn, thisArg) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
}
var a = [], r;
for (var k = 0; k < this.length; k++) {
if (r = callbackfn.call(thisArg, this[k])) {
a.push(r);
}
}
return a;
};
// 15.4.4.21 Array.prototype.reduce(callbackfn[, initialValue])
Array.prototype.reduce = function (callbackfn, initialValue) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
} else if (this.length === 0 && initialValue === undefined) {
throw TypeError("Reduce of empty array with no initial value");
}
var accumulator, k;
if (initialValue) {
accumulator = initialValue;
k = 0;
} else {
accumulator = this[0];
k = 1;
}
for (; k < this.length; k++) {
accumulator = callbackfn.call(undefined, accumulator, this[k], k, this);
}
return accumulator
};
// 15.4.4.22 Array.prototype.reduceRight(callbackfn[, initialValue])
Array.prototype.reduceRight = function (callbackfn, initialValue) {
if (typeof callbackfn !== "function") {
throw TypeError("" + callbackfn + " is not a function");
} else if (this.length === 0 && initialValue === undefined) {
throw TypeError("Reduce of empty array with no initial value");
}
var accumulator, k;
if (initialValue) {
accumulator = initialValue;
k = this.length - 1;
} else {
accumulator = this[this.length - 1];
k = this.lengh - 2;
}
for (; k >= 0; k-- {
accumulator = callbackfn.call(undefined, accumulator, this[k], k, this);
}
return accumulator
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment