I've constructed a rather useful function to identify data-types; however, while coding happily I was rudely interrupted with a rather worrying dilemma.
As you may know, after calling .bind({foo:'bar'})
on a closure, you cannot access said foo
property "externally"; however, inside the closure, this.foo
works.
Also, when assigning something in such a way, you often face a throw: intermediary ... blah blah is undefined
when you try access a property - directly after defining it. The code below fixes these issues but...
The problem is explained after the code:
"use strict";
if ('undefined' == typeof global)
{
Object.defineProperty
(
window,'global',
{
writable:false,
configurable:false,
enumerable:false,
value:window
}
);
}
Object.defineProperty
(
Function.prototype, 'wrap',
{
writable:false,
enumerable:false,
configurable:false,
value:function(jsob)
{
this.bind(jsob);
for (var i in jsob)
{ this[i] = jsob[i]; }
return this;
}
}
);
global.typeOf = function(data)
{
if ((data === null) || (data === undefined))
{ return 'void'; }
if ((data === true) || (data === false))
{ return 'bool'; }
var tpof = (({}).toString.call(data).match(/\s([a-zA-Z]+)/)[1].toLowerCase());
if ((tpof == 'array') || (tpof == 'htmlcollection') || (tpof == 'namednodemap'))
{ return 'list'; }
if ((tpof == 'global') || (tpof == 'window'))
{ return 'glob'; }
switch (tpof.substr(0,6))
{
case 'number': return 'unit';
case 'string': return (/[^\x20-\x7E\t\r\n]/.test(data) ? 'blob' : 'text');
case 'object': return 'jsob';
case 'functi': return 'func';
default: return 'node';
}
}
.wrap
({
list:'void bool unit text blob list jsob func node glob'.split(' '),
init:function()
{
this.list.forEach(function(item)
{
global[(item.toUpperCase())] = item;
global[('is'+(item[0].toUpperCase() + item.substr(1,item.length)))] = function(data)
{
return ((typeOf(data) == this.text) ? true : false);
}
.bind({text:item.toLowerCase()}); // <-- ISSUE
});
return this;
}
}).init();
So the little wrapper
above takes care of such weirdness; however, have a look on the line where <-- ISSUE
is; see, I cannot use wrap()
there, I have to use bind()
, else - inside the function - this
is undefined!!
Let me clarify: If you use the entire code just as it is above in <script>
tags inside a brand-spanking-new html file; just change that ISSUE
line's bind
word to: wrap
; then try something like: isText("bite me!");
You will see an error that specifies something like:
cannot read property "text" from undefined ..
so; if you do a console.log(this)
inside that function definition there; you will see undefined
.
If anyone could help fixing this, or at least explain why this is happening, I'd really appreciate the input.