base-class-extend
Advanced tools
Comparing version 0.0.14 to 0.0.15
// base-class-extend.js | ||
(function () { | ||
this.BaseClass = function () { | ||
'use strict'; | ||
// defProp | ||
var defProp = function (obj) { | ||
if (!Object.defineProperty) return null; | ||
try { | ||
Object.defineProperty(obj, 'prop', {value: 'value'}); | ||
return obj.prop === 'value' ? Object.defineProperty : null; | ||
} catch (err) { return null; } | ||
} ({}); | ||
// setConst(obj, prop, val) | ||
var setConst = Object.defineProperty ? | ||
var setConst = defProp ? | ||
function setConst(obj, prop, val) { | ||
Object.defineProperty(obj, prop, {value: val}); } : | ||
defProp(obj, prop, {value: val}); } : | ||
function setConst(obj, prop, val) { obj[prop] = val; }; | ||
// setValue(obj, prop, val) | ||
var setValue = Object.defineProperty ? | ||
var setValue = defProp ? | ||
function setValue(obj, prop, val) { | ||
Object.defineProperty(obj, prop, {value: val, | ||
defProp(obj, prop, {value: val, | ||
writable: true, configurable: true}); } : | ||
function setValue(obj, prop, val) { obj[prop] = val; }; | ||
// getProto(obj) | ||
var getProto = Object.getPrototypeOf || {}.__proto__ ? | ||
function getProto(obj) { return obj.__proto__; } : null; | ||
// setProto(obj, proto) | ||
var setProto = Object.setPrototypeOf ? Object.setPrototypeOf : | ||
function setProto(obj, proto) { obj.__proto__ = proto; }; | ||
var setProto = Object.setPrototypeOf || {}.__proto__ ? | ||
function setProto(obj, proto) { obj.__proto__ = proto; } : null; | ||
// getProto(obj) | ||
var getProto = Object.getPrototypeOf ? Object.getPrototypeOf : | ||
function getProto(obj) { return obj.__proto__; }; | ||
// defGetter | ||
var defGetter = defProp ? | ||
function defGetter(obj, prop, getter) { | ||
return defProp(obj, prop, {get: getter}); } : | ||
Object.prototype.__defineGetter__ ? | ||
function defGetter(obj, prop, getter) { | ||
return obj.__defineGetter__(prop, getter); } : | ||
function defGetter(obj, prop, getter) {}; | ||
@@ -30,20 +48,84 @@ // fnameRegExp: function name regular expression | ||
// fname: get function name | ||
function fname() { | ||
return ('' + this).replace(fnameRegExp, '$1'); | ||
// Function.prototype.name | ||
if (!Function.prototype.hasOwnProperty('name')) | ||
defGetter(Function.prototype, 'name', | ||
function nameOfFunction() { | ||
return ('' + this).replace(fnameRegExp, '$1'); }); | ||
// namedFunc(name, fn) | ||
function namedFunc(name, fn) { | ||
if (!name || fn.name === name) return fn; | ||
try { fn.name = name; if (fn.name === name) return fn; } catch (err) {} | ||
try { | ||
var func = Function('fn', 'return function ' + name + '() { ' + | ||
'return fn.apply(this, arguments); }')(fn); | ||
} catch (err) { | ||
try { | ||
var func = Function('fn', 'return function ' + name + '_() { ' + | ||
'return fn.apply(this, arguments); }')(fn); | ||
} catch (err) { | ||
return fn; | ||
} | ||
} | ||
func.prototype = fn.prototype; | ||
if (func.name === name) return func; | ||
try { func.name = name; } catch (err) {} | ||
return func; | ||
} | ||
// Function.prototype.name | ||
if (!Function.prototype.hasOwnProperty('name')) { | ||
if (Object.defineProperty) | ||
Object.defineProperty(Function.prototype, 'name', {get: fname}); | ||
else if (Object.prototype.__defineGetter__) | ||
Function.prototype.__defineGetter__('name', fname); | ||
// Base.create(...args) or Base.new(...args) | ||
var Base_create = setProto ? function Base_create() { | ||
if (this.prototype instanceof Array) { | ||
var obj = Array.apply(null, arguments); | ||
setProto(obj, this.prototype); | ||
} | ||
else if (this.prototype instanceof Error) { | ||
var obj = Error.apply(null, arguments); | ||
if (!obj.hasOwnProperty('message') && | ||
typeof arguments[0] === 'string') | ||
obj.message = arguments[0]; | ||
if (typeof obj.stack === 'string') | ||
obj.stack = obj.stack.split('\n').filter(function (str) { | ||
return !/((base-class-extend.js)|(Base_create))/.test(str); | ||
}).join('\n'); | ||
setProto(obj, this.prototype); | ||
} | ||
else | ||
var obj = Object.create(this.prototype); | ||
return this.apply(obj, arguments), obj; | ||
} : | ||
function Base_create() { | ||
if (typeof this !== 'function') | ||
return Object.apply(null, arguments); | ||
function __() {} | ||
__.prototype = this.prototype; | ||
var obj = new __(); | ||
return this.apply(obj, arguments), obj; | ||
}; | ||
// Base.addPrototype(proto) | ||
var Base_addPrototype = setProto ? | ||
function Base_addPrototype(proto) { | ||
setProto(proto, getProto(this)); | ||
setProto(this, proto); | ||
return proto; | ||
} : | ||
function Base_addPrototype(proto) { | ||
for (var p in proto) | ||
if (proto.hasOwnProperty(p)) | ||
this[p] = proto[p]; | ||
return this; | ||
}; | ||
// chainProto(obj, proto) | ||
function chainProto(obj, proto) { | ||
return Base_addPrototype.call(obj, proto); | ||
} | ||
// Base.extend([name], [proto], [staticProps]) | ||
// Base.extend([name], [proto], [props]) | ||
// Usage: | ||
// var SimpleClass = | ||
// Base.extend( | ||
// {new: function SimpleClass() { | ||
// {constructor: function SimpleClass() { | ||
// SimpleClass.super_.call(this); | ||
@@ -55,144 +137,159 @@ // this.prop1 = 'val'; }, | ||
// {classMethod1: function () {}}); | ||
function Base_extend(name, proto, staticProps) { | ||
var Base_extend = setProto ? function Base_extend(name, proto, props) { | ||
// check argument: name | ||
if (typeof name !== 'string') { | ||
staticProps = proto; | ||
proto = name; | ||
name = ''; | ||
} | ||
if (typeof name !== 'string') | ||
props = proto, proto = name, name = ''; | ||
if (!proto || typeof proto !== 'object') proto = {}; | ||
var superCtor = typeof this === 'function' ? this : Object; | ||
var _super = typeof this === 'function' ? this : Object; | ||
var ctor = proto.hasOwnProperty('constructor') ? proto.constructor : | ||
proto.hasOwnProperty('new') ? proto['new'] : | ||
Function('proto, superCtor, Base_create', | ||
'return function ' + name + '() {\n' + | ||
' "use strict";' + | ||
' if (!(this instanceof proto.constructor) ||\n' + | ||
' this instanceof Array && !this.hasOwnProperty("length") ||\n' + | ||
' this instanceof Error && !this.hasOwnProperty("message"))\n' + | ||
' return Base_create.apply(proto.constructor, arguments);\n' + | ||
' if (superCtor !== Object && superCtor !== Array && superCtor !== Error)\n' + | ||
' superCtor.apply(this, arguments); }') | ||
(proto, superCtor, Base_create); | ||
function () { | ||
if (!(this instanceof proto.constructor) || | ||
this instanceof Array && !this.hasOwnProperty('length') || | ||
this instanceof Error && !this.hasOwnProperty('message')) | ||
return Base_create.apply(proto.constructor, arguments); | ||
if (_super !== Object && _super !== Array && _super !== Error) | ||
_super.apply(this, arguments); }; | ||
if (typeof ctor !== 'function') | ||
throw new TypeError('constructor must be a function'); | ||
if (!ctor.name && name !== '') { | ||
ctor.prototype = proto; | ||
ctor = Function('proto, ctor, Base_create', | ||
'return function ' + name + '() {\n' + | ||
' "use strict";' + | ||
' if (!(this instanceof proto.constructor) ||\n' + | ||
' this instanceof Array && !this.hasOwnProperty("length") ||\n' + | ||
' this instanceof Error && !this.hasOwnProperty("message"))\n' + | ||
' return Base_create.apply(proto.constructor, arguments);\n' + | ||
' ctor.apply(this, arguments); }') | ||
(proto, ctor, Base_create); | ||
} | ||
ctor.prototype = proto; | ||
ctor = namedFunc(name, ctor); | ||
// add name to methods/functions if not has name | ||
for (var key in proto) | ||
if (typeof proto[key] === 'function' && !proto[key].name) | ||
proto[key] = namedFunc(key, proto[key]); | ||
// delete constructor | ||
delete proto.constructor; | ||
delete proto['new']; | ||
// override constructor | ||
delete proto['new']; | ||
setValue(proto, 'constructor', ctor); | ||
// inherits from super constructor | ||
setProto(proto, superCtor.prototype); | ||
setProto(proto, _super.prototype); | ||
// constructor.__proto__ -> for inherits class methods | ||
if (staticProps == null || typeof staticProps !== 'object') { | ||
setProto(ctor, superCtor === Object ? Function.prototype : superCtor); | ||
if (props == null || typeof props !== 'object') { | ||
setProto(ctor, _super === Object ? Function.prototype : _super); | ||
} | ||
else { | ||
setProto(ctor, staticProps); | ||
setProto(staticProps, superCtor === Object ? Function.prototype : superCtor); | ||
// class initializer: init | ||
var init = staticProps.hasOwnProperty('init') && staticProps.init; | ||
delete staticProps.init; | ||
var init = props.hasOwnProperty('init') && props.init; | ||
delete props.init; | ||
if (typeof init === 'function') init.call(ctor); | ||
// add name to methods/functions if not found | ||
var keys = Object.keys(staticProps); | ||
for (var i = 0, n = keys.length; i < n; ++i) { | ||
var key = keys[i]; | ||
if (typeof staticProps[key] === 'function' && | ||
!staticProps[key].name) { | ||
staticProps[key] = Function('fn', | ||
'return function ' + key + '_() {\n' + | ||
' return fn.apply(this, arguments); }') | ||
(staticProps[key]); | ||
} | ||
} | ||
// add name to methods/functions if not has name | ||
for (var key in props) | ||
if (typeof props[key] === 'function' && !props[key].name) | ||
props[key] = namedFunc(key, props[key]); | ||
setProto(ctor, props); | ||
setProto(props, _super === Object ? Function.prototype : _super); | ||
} | ||
// add methods and class methods if not found (in prototype chain) | ||
if (ctor.extend !== Base_extend) ctor.extend = Base_extend; | ||
if (ctor.create !== Base_create) ctor.create = Base_create; | ||
if (ctor['new'] !== Base_create) ctor['new'] = Base_create; | ||
if (ctor.extend !== Base_extend) setValue(ctor, 'extend', Base_extend); | ||
if (ctor.create !== Base_create) setValue(ctor, 'create', Base_create); | ||
if (ctor['new'] !== Base_create) setValue(ctor, 'new', Base_create); | ||
if (!('private' in proto)) proto['private'] = Base_addPrototype; | ||
if (!('addPrototype' in proto)) proto['addPrototype'] = Base_addPrototype; | ||
if (proto['private'] !== Base_addPrototype) setValue(proto, 'private', Base_addPrototype); | ||
if (proto.addPrototype !== Base_addPrototype) setValue(proto, 'addPrototype', Base_addPrototype); | ||
// constructor.super_ -> for points super class | ||
setConst(ctor, 'super_', superCtor); | ||
setConst(ctor, 'super', superCtor); | ||
setConst(ctor, 'super_', _super); | ||
setConst(ctor, 'super', _super); | ||
return ctor; | ||
} | ||
} : | ||
function Base_extend(name, proto, props) { | ||
'use strict'; | ||
// Base.new(...args) or Base.create(...args) | ||
function Base_create() { | ||
if (this.prototype instanceof Array) { | ||
var obj = Array.apply(null, arguments); | ||
setProto(obj, this.prototype); | ||
} | ||
else if (this.prototype instanceof Error) { | ||
var obj = Error.apply(null, arguments); | ||
if (!obj.hasOwnProperty('message') && | ||
typeof arguments[0] === 'string') | ||
obj.message = arguments[0]; | ||
if (typeof obj.stack === 'string') | ||
obj.stack = obj.stack.split('\n').filter(function (str) { | ||
return !/((base-class.js)|(Base_create))/.test(str); | ||
}).join('\n'); | ||
setProto(obj, this.prototype); | ||
} | ||
else | ||
var obj = Object.create(this.prototype); | ||
return this.apply(obj, arguments), obj; | ||
} | ||
// check argument: name | ||
if (typeof name !== 'string') | ||
props = proto, proto = name, name = ''; | ||
// Base.addPrototype(proto) | ||
function Base_addPrototype(proto) { | ||
setProto(proto, getProto(this)); | ||
setProto(this, proto); | ||
return proto; | ||
} | ||
if (!proto || typeof proto !== 'object') proto = {}; | ||
var _super = typeof this === 'function' ? this : Object; | ||
// Base.extendPrototype([ctor = Function]) | ||
var ctor = proto.hasOwnProperty('constructor') ? proto.constructor : | ||
proto.hasOwnProperty('new') ? proto['new'] : | ||
function () { | ||
if (!(this instanceof proto.constructor) || | ||
this instanceof Array && !this.hasOwnProperty('length') || | ||
this instanceof Error && !this.hasOwnProperty('message')) | ||
return Base_create.apply(proto.constructor, arguments); | ||
if (_super !== Object && _super !== Array && _super !== Error) | ||
_super.apply(this, arguments); }; | ||
ctor = namedFunc(name, ctor); | ||
function __() { setValue(this, 'constructor', ctor); } | ||
__.prototype = _super.prototype; | ||
ctor.prototype = new __(); | ||
// delete constructor | ||
delete proto.constructor; | ||
delete proto['new']; | ||
for (var p in proto) | ||
if (proto.hasOwnProperty(p)) | ||
setValue(ctor.prototype, p, proto[p]); | ||
proto = ctor.prototype; | ||
setValue(proto, 'constructor', ctor); | ||
// copy super class props | ||
for (var p in _super) | ||
if (p !== 'name' && !ctor.hasOwnProperty(p) && | ||
_super.hasOwnProperty(p)) | ||
setValue(ctor, p, _super[p]); | ||
// copy static class props | ||
if (props) | ||
for (var p in props) | ||
if (props.hasOwnProperty(p)) | ||
setValue(ctor, p, props[p]); | ||
// add methods and class methods if not found (in prototype chain) | ||
if (ctor.extend !== Base_extend) setValue(ctor, 'extend', Base_extend); | ||
if (ctor.create !== Base_create) setValue(ctor, 'create', Base_create); | ||
if (ctor['new'] !== Base_create) setValue(ctor, 'new', Base_create); | ||
if (ctor.prototype['private'] !== Base_addPrototype) | ||
setValue(ctor.prototype, 'private', Base_addPrototype); | ||
if (ctor.prototype.addPrototype !== Base_addPrototype) | ||
setValue(ctor.prototype, 'addPrototype', Base_addPrototype); | ||
// constructor.super_ -> for points super class | ||
setConst(ctor, 'super_', _super); | ||
setConst(ctor, 'super', _super); | ||
if (ctor.__proto__) ctor.__proto__ = _super; | ||
return ctor; | ||
}; // Base_extend | ||
// Base.extendPrototype([ctor = Function.prototype]) | ||
function Base_extendPrototype(ctor) { | ||
if (typeof ctor !== 'function') ctor = Function.prototype; | ||
ctor.extend = Base_extend; | ||
if (ctor.extend !== Base_extend) setValue(ctor, 'extend', Base_extend); | ||
return this; | ||
} | ||
var Base = Base_extend('Base', | ||
{'private': Base_addPrototype, | ||
addPrototype : Base_addPrototype}, | ||
{extend: Base_extend, | ||
create: Base_create, | ||
'new': Base_create, | ||
extendPrototype: Base_extendPrototype}); | ||
// Base | ||
var Base = Base_extend('Base', {}, {extendPrototype: Base_extendPrototype}); | ||
// exports | ||
if (typeof module !== 'undefined') { | ||
module.exports = exports = Base; | ||
} | ||
else { | ||
var g = Function('return this')(); | ||
g.BaseClass = Base; | ||
} | ||
if (typeof module === 'object' && module && module.exports) | ||
module.exports = Base; | ||
})(); | ||
return Base; | ||
}(); |
{ | ||
"name": "base-class-extend", | ||
"version": "0.0.14", | ||
"version": "0.0.15", | ||
"description": "Base Class constructor for easy class definition - supports getter/setter, inherit/extend Array Error or EventEmitter etc", | ||
"main": "lib/base-class-extend.js", | ||
"devDependencies": { | ||
"get-constructors": ">=0.0.4" | ||
"get-constructors": ">=0.0.14" | ||
}, | ||
@@ -23,3 +23,3 @@ "keywords": [ | ||
"type": "git", | ||
"url": "https://github.com/LightSpeedWorks/base-class-extend" | ||
"url": "LightSpeedWorks/base-class-extend" | ||
}, | ||
@@ -26,0 +26,0 @@ "bugs": { |
@@ -18,2 +18,4 @@ [base-class-extend](https://www.npmjs.org/package/base-class-extend) - npm | ||
Chrome, Firefox, ie11/9/8/6 と Node.js/io.js をサポートします。 | ||
関連記事: [[JavaScript] getter/setterも使えるエコ楽なクラス定義 - もちろん継承も - private変数も](http://qiita.com/LightSpeedC/items/3946088b58925234cc48) - qiita | ||
@@ -20,0 +22,0 @@ |
@@ -17,2 +17,4 @@ [base-class-extend](https://www.npmjs.org/package/base-class-extend) - npm | ||
Supports Chrome, Firefox, ie11/9/8/6 and Node.js/io.js. | ||
[Japanese version/■日本語版はこちら■](README-JP.md#readme) | ||
@@ -19,0 +21,0 @@ |
@@ -72,3 +72,3 @@ // test-en.js | ||
var Elephant = Animal.extend('Elephant', { | ||
new: function () { | ||
new: function (name) { | ||
if (!(this instanceof Elephant)) | ||
@@ -75,0 +75,0 @@ return new Elephant(name); |
@@ -69,3 +69,3 @@ // test-jp.js | ||
var Elephant = Animal.extend('Elephant', { | ||
new: function () { | ||
new: function (name) { | ||
if (!(this instanceof Elephant)) | ||
@@ -72,0 +72,0 @@ return new Elephant(name); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
458003
884
448
25