Javascript function to read object's property (instrumenting read object's property) - javascript

The question:
How can a I implement a function in JavaScript which would behave exactly the same as read property,
but will log the values
I.e.
function f(obj, prop) {
console.log(obj, prop, obj[prop]);
return obj[prop];
}
But with respect to preserving this value and other pitfalls.
Question context: I'm developing some instrumetation tool for Javascript.
I'm using Babel to parse the code, than I manipulate AST tree to replace reads from object properties.
For source code
a.b[5].c(1,2,3);
I produce instrumented code like this one:
const LOG_READ = (z)=> {console.log('LOGGED', z); return z;}
LOG_READ(
LOG_READ(
LOG_READ(
a
, "b")
, 5)
, "c")(1,2,3);
I had a problem with:
let x = [1,2,3];
x.map(it => console.log(it));
Instrumented to:
let x = [1,2,3];
LOG_READ(x, "map")(it => console.log(it));
It failed to run when instrumented, because "map" expects "this" to be equal to "x" which isn't.
When I fixed LOG_READ to
const LOG_READ = (obj, prop)=> {console.log('LOGGED', z); return (typeof z === "function" ? obj[prop].bind(obj) : z}
It failed for
class c1 extends LOG_READ(module, "func_name") {...}
Because bind should not be called for this case, so it became:
const LOG_READ = (obj, prop)=> {console.log('LOGGED', obj, prop); return (typeof obj[prop] === "function" && !obj[prop].prototype ? obj[prop].bind(obj) : obj[prop]}
As you might guess it failed again in some else place.
I've also tried making a proxy or an expression instead of function - they also don't work.
I.e. (LOG_WRITE_PROXY.w = a.map)(it => console.log(it));
So here is why I'm asking this question.

Someone linked Proxy in a comment, however a bit later the comment disappeared. I thought there would an answer come, but apparently it has not.
However Proxy seems to be related and interesting, see this test:
var something={
a:1,
b:[2,3,4],
c:{
d:"Hello",
e:[5,6,7]
}
};
var handler = {
get: function(obj, prop) {
console.log(prop.toString()+" requested: "+obj[prop]);
if(prop in obj){
var p=obj[prop];
if(p instanceof Object || p instanceof Array)
return new Proxy(p,handler);
return p;
}
return undefined;
}
};
var proxd=new Proxy(something,handler);
console.log(proxd.a+proxd.b.reduce((a,i)=>a+i)+proxd.c.e[2]);
So it does something with this simple throwaway recursion already, like cutting through the this issue appearing in the comments (reduce just works fine).

Related

Is there a way for the value of an object to be made aware of its own key dynamically?

This is a purely theoretical question here (though one I think is an interesting thought exercise). I was just working on a JavaScript object (documentation-related) and the somewhat-unusual thought crosses my mind: is there a way to make a key/value pair entry within said object capable of reading its own key as part of its value? That is to say:
Assuming I have a JavaScript object used for the purposes of serializing data:
{
"someKey":()=>"M-me? MY key is '" + voodoo(this) + "'! Thanks so much for taking an interest!"
}
...is there a way I can get "M-me? MY key is 'someKey'! Thanks so much for taking an interest!" as an (albeit: rather asinine) output when addressing the key? I totally don't care what the structure would look like, nor what the type of the Value of the portion of the KVP would be, NOR what arguments would need passed it (if any? I'm just assuming it would have to be a function, after all).
I mean, of course it's possible; it's code. It's ALL possible (I've seen a quine that can ascertain its own SHA-512 hash, for heaven sake). But I find it to be an interesting thought experiment, and wanted to see if anyone already had some Code Kung Fu/Source Santeria (even at the abstract/pseudo-code level) and/or someone that might have some ideas.
I've tinkered with going so far as to actually parse the JavaScript source file line-by-line and test for the remainder of the output string to place it (worked, but lame... What if it's a constructed object?), then thought of stringifying it and RegEx-ing it out (worked, but still pretty weak... Relies too much on advance knowledge of what would have to be an unchanging structure).
I'm now fiddling with attempting to filter the object on and by itself to try and isolate the key making the request, which I expect will work (-ish), but still leaves me feeling kind of like the bull in a china shop. I can extend the Object prototype (I know, I know. Theoretical, remember?) so the self-reference doesn't pose a problem, but I'm stumped as to providing a means for the KVP to identify itself uniquely without having to search for some set portion of string.
Anyone have any thoughts? No holds barred: this will probably never see the light of a production environment - just an interesting puzzle - so feel free to muck with prototypes, include libraries, fail to indent... whatever*. Frankly, it doesn't really even have to be in JavaScript; that's just what I'M using. It's 2:30am here, and I'm just noodling on if it's DOABLE.
* (Please don't fail to indent. Twitch-twitch (ಥ∻.⊙) It seems I lied about that part.)
Reflexively lookup the key on call
This is probably the most surefire way to do it. When obj.foo() is called, then foo is executed with obj set as the value of this. This means that we can lookup the key from this. We can examine the object easily the hardest thing is to find which key contains the function we just executed. We can try to do string matching but it might fail for:
const obj = {
foo: function() { /* magic */ },
bar: function() { /* magic */ },
}
Because the contents of the functions will be the same but the keys are different, so it's not easy to differentiate between obj.foo() and obj.bar() by doing string matching.
However, there is a better option - naming the function:
const obj = {
foo: function lookUpMyOwnKey() { /* magic */ }
}
Normally, there is pretty much no effect whether you give the function a name or not. However, the thing that we can leverage is that the function can now refer to itself by the name. This gives us a fairly straightforward solution using Object.entries:
"use strict";
const fn = function lookUpMyOwnName() {
if (typeof this !== "object" || this === null) { //in case the context is removed
return "Sorry, I don't know";
}
const pair = Object.entries(this)
.find(([, value]) => value === lookUpMyOwnName);
if (!pair) {
return "I can't seem to find out";
}
return `My name is: ${pair[0]}`
}
const obj = {
foo: fn
}
console.log(obj.foo());
console.log(obj.foo.call(null));
console.log(obj.foo.call("some string"));
console.log(obj.foo.call({
other: "object"
}));
This is pretty close to the perfect solution. As we can see, it even works if the function is not defined as part of the object but added later. So, it's completely divorced from what object it's part of. The problem is that it's still one function and adding it multiple times will not get the correct result:
"use strict";
const fn = function lookUpMyOwnName() {
if (typeof this !== "object" || this === null) { //in case the context is removed
return "Sorry, I don't know";
}
const pair = Object.entries(this)
.find(([, value]) => value === lookUpMyOwnName);
if (!pair) {
return "I can't seem to find out";
}
return `My name is: ${pair[0]}`
}
const obj = {
foo: fn,
bar: fn
}
console.log(obj.foo()); // foo
console.log(obj.bar()); // foo...oops
Luckily, that's easily solvable by having a higher order function and creating lookUpMyOwnName on the fly. This way different instances are not going to recognise each other:
"use strict";
const makeFn = () => function lookUpMyOwnName() {
// ^^^^^^ ^^^^^
if (typeof this !== "object" || this === null) { //in case the context is removed
return "Sorry, I don't know";
}
const pair = Object.entries(this)
.find(([, value]) => value === lookUpMyOwnName);
if (!pair) {
return "I can't seem to find out";
}
return `My name is: ${pair[0]}`
}
const obj = {
foo: makeFn(),
bar: makeFn()
}
console.log(obj.foo()); // foo
console.log(obj.bar()); // bar
Making really sure we find the key
There are still ways this could fail
If the call comes from the prototype chain
If the property is non-enumerable
Example:
"use strict";
const makeFn = () => function lookUpMyOwnName() {
// ^^^^^^ ^^^^^
if (typeof this !== "object" || this === null) { //in case the context is removed
return "Sorry, I don't know";
}
const pair = Object.entries(this)
.find(([, value]) => value === lookUpMyOwnName);
if (!pair) {
return "I can't seem to find out";
}
return `My name is: ${pair[0]}`
}
const obj = {
foo: makeFn()
}
const obj2 = Object.create(obj);
console.log(obj.foo()); // foo
console.log(obj2.foo()); // unknown
const obj3 = Object.defineProperties({}, {
foo: {
value: makeFn(),
enumerable: true
},
bar: {
value: makeFn(),
enumerable: false
}
})
console.log(obj3.foo()); // foo
console.log(obj3.bar()); // unknown
Is it worth making an overengineered solution that solves a non-existing problem just to find everything here?
Well, I don't know the answer to that. I'll make it anyway - here is a function that thoroughly checks its host object and its prototype chain via Object.getOwnPropertyDescriptors to find where exactly it was called from:
"use strict";
const makeFn = () => function lookUpMyOwnName() {
if (typeof this !== "object" || this === null) {
return "Sorry, I don't know";
}
const pair = Object.entries(Object.getOwnPropertyDescriptors(this))
.find(([propName]) => this[propName] === lookUpMyOwnName);
if (!pair) {//we must go DEEPER!
return lookUpMyOwnName.call(Object.getPrototypeOf(this));
}
return `My name is: ${pair[0]}`;
}
const obj = {
foo: makeFn()
}
const obj2 = Object.create(obj);
console.log(obj.foo()); // foo
console.log(obj2.foo()); // foo
const obj3 = Object.defineProperties({}, {
foo: {
value: makeFn(),
enumerable: true
},
bar: {
value: makeFn(),
enumerable: false
},
baz: {
get: (value => () => value)(makeFn()) //make a getter from an IIFE
}
})
console.log(obj3.foo()); // foo
console.log(obj3.bar()); // bar
console.log(obj3.baz()); // baz
Use a proxy (slight cheating)
This is an alternative. Define a Proxy that intercepts all calls to the object and this can directly tell you what was called. It's a bit of a cheat, as the function doesn't really lookup itself but from the outside it might look like this.
Still probably worth listing, as it has the advantage of being extremely powerful with a low overhead cost. No need to recursively walk the prototype chain and all possible properties to find the one:
"use strict";
//make a symbol to avoid looking up the function by its name in the proxy
//and to serve as the placement for the name
const tellMe = Symbol("Hey, Proxy, tell me my key!");
const fn = function ItrustTheProxyWillTellMe() {
return `My name is: ${ItrustTheProxyWillTellMe[tellMe]}`;
}
fn[tellMe] = true;
const proxyHandler = {
get: function(target, prop) { ///intercept any `get` calls
const val = Reflect.get(...arguments);
//if the target is a function that wants to know its key
if (val && typeof val === "function" && tellMe in val) {
//attach the key as ##tellMe on the function
val[tellMe] = prop;
}
return val;
}
};
//all properties share the same function
const protoObj = Object.defineProperties({}, {
foo: {
value: fn,
enumerable: true
},
bar: {
value: fn,
enumerable: false
},
baz: {
get() { return fn; }
}
});
const derivedObj = Object.create(protoObj);
const obj = new Proxy(derivedObj, proxyHandler);
console.log(obj.foo()); // foo
console.log(obj.bar()); // bar
console.log(obj.baz()); // baz
Take a peek at the call stack
This is sloppy and unreliable but still an option. It will be very dependant on the environment where this code, so I will avoid making an implementation, as it would need to be tied to the StackSnippet sandbox.
However, the crux of the entire thing is to examine the stack trace of where the function is called from. This will have different formatting in different places. The practice is extremely dodgy and brittle but it does reveal more context about a call than what you can normally get. It might be weirdly useful in specific circumstances.
The technique is shown in this article by David Walsh and here is the short of it - we can create an Error object which will automatically collect the stacktrace. Presumably so we can throw it and examine it later. Instead we can just examine it now and continue:
// The magic
console.log(new Error().stack);
/* SAMPLE:
Error
at Object.module.exports.request (/home/vagrant/src/kumascript/lib/kumascript/caching.js:366:17)
at attempt (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:180:24)
at ks_utils.Class.get (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:194:9)
at /home/vagrant/src/kumascript/lib/kumascript/macros.js:282:24
at /home/vagrant/src/kumascript/node_modules/async/lib/async.js:118:13
at Array.forEach (native)
at _each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:39:24)
at Object.async.each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:117:9)
at ks_utils.Class.reloadTemplates (/home/vagrant/src/kumascript/lib/kumascript/macros.js:281:19)
at ks_utils.Class.process (/home/vagrant/src/kumascript/lib/kumascript/macros.js:217:15)
*/

How to detect the end of a get sequence in a proxy object?

In order to avoid error when accessing deeply nested properties, I wrote a proxy-returning function:
const safe_access = obj =>
new Proxy(obj, {
get: (o, k) =>
o[k] == null
? safe_access({})
: typeof o[k] === 'object'
? safe_access(o[k])
: o[k] });
Here's an example:
const a = safe_access({});
a.x.y.z; // no TypeError 🎉
However in its current form safe_access is unable to tell when it has reached the end of the path. Meaning that it cannot return undefined to signify that the property truly doesn't exist. This also means that you cannot have default values:
const a = safe_access({});
a.x.y.z || 42; // not 42
const {x: {y: {z = 42}}} = a;
z; // not 42
How can my proxy object detect the end of a property lookup?
This answer more or less applies here, for the same reasons.
You can't detect the end of an access chain because nothing makes it any different from the preceding accesses. At runtime, the following code is effectively identical to let r = a.x.y.z.
let r = a;
{
r = r.x;
r = r.y;
r = r.z
}
If you actually want to use this sort of safe navigation in code you're writing, the best is to use the optional chaining (?.) and nullish coalescing (??) operators added to the Javascript standard in 2020. They provide a neater, less confusing way to do this sort of thing, and are supported by all modern browsers.
let r = a?.x?.y?.z ?? 42;
If you need to support legacy browsers, you can get these operators from these two Babel plugins: ([1], [2]).
However, if you really want to implement "safe" access yourself, there are a few tricks you can use to get around this.
One trick, that probably requires the least additional work is to reserve one name to indicate the end of the safe access chain. (I've done something similar in Python in the past.)
function safe_access(value) {
let obj = (typeof(value) === 'object') ? value : {};
return new Proxy(obj, {
value: value,
get: function(target, property) {
if (property === "$")
return this.value;
else
return safe_access(target[property]);
}
});
}
let a = {'x': {'y': 123}};
// a.x.y is a proxy object
a.x.y.$ === 123
a.x.y.z.$ === undefined
Another trick is detailed in this blog post.
An interesting option is to work with Promises. Comlink has an interesting usage of this.
Expanding on jirassimok's answer, if everything is async, then the termination token becomes "then".
function safe_access(value) {
let obj = (typeof value === 'object') ? value : {};
return new Proxy(obj, {
value: value,
get: function(target, property) {
if (property === "then")
return this.value;
else
return safe_access(target[property]);
}
});
}
async function main() {
let a = safe_access({'x': {'y': 123}});
// a.x.y is a proxy object
(await a.x.y) === 123
(await a.x.y.z) === undefined
}
main();
This wasn't immediately obvious to me, as I've been using async/await for a long time now.

es6 proxy safe deep object

I wrote a small wrapper to return undefined in place of typeError when accessing properties that don't exist using a Proxy. Here is the code:
function proxify(event) {
var proxy = new Proxy(event, {
get: function (target, property) {
if (property in target) {
return target[property];
} else {
return '';
}
}
}
});
return proxy;
}
This works when a property is missing 1 level deep.
For example, assuming obj.something does not exist:
obj.something.else
will return undefined
But if the object property is deep nested
obj.something.else.deeper
I receive a typeError
My question is how do I extend the function above to work on deep nested objects?
Thx
You need to wrap the return value in your proxify function:
function proxify(event) {
return isPrimitive(event) ? event : new Proxy(event, { get: getProp });
}
function isPrimitive(v) {
return v == null || (typeof v !== 'function' && typeof v !== 'object');
}
function getProp (target, property) {
if (property in target) {
return proxify(target[property]);
} else {
return proxify({});
}
}
In all honesty, you're probably better off using something like lodash's _.get() or ramda's R.path(). There's no way to know from the first getProp() call how many layers deep the evaluation is going to go, so it has to always return a primitive value or a "truthy" Proxy instance so that the next property access can be intercepted (if one happens). The _.get() method on the other hand takes a string so it can immediately know from the initial invocation that you're only trying to access down so many levels.
I published a library on GitHub (Observable Slim) that enables you to proxy an object and any nested children of that object. It also has a few extra features:
Reports back to a specified callback whenever changes occur.
Will prevent user from trying to Proxy a Proxy.
Keeps a store of which objects have been proxied and will re-use existing proxies instead of creating new ones (very significant performance implications).
Written in ES5 and employs a forked version of the Proxy polyfill so it can be deployed in older browsers fairly easily and support Array mutation methods.
It works like this:
var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
console.log(JSON.stringify(changes));
});
p.testing.blah = 42; // console: [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
As idbehold said, you must return a primitive value or new proxy.
I think you dont need loDash to do that, and Yes, you can manage the depth of the nested proxy ! (see my last point, deepProxy.
But, since I'm not sure what you want to do, i would like focus your attention to those few points:
First usage (simulated chain):
function proxify(event){
return isPrimitive(event) ? event : new Proxy(event,{ get: getProp });
}
function isPrimitive(v){
return v == null || (typeof v !== 'function' && typeof v !== 'object');
}
function getProp(target, property){
return (property in target)
? proxify(target[property])
: proxify({});
}
this code as it stands, will simulate nested properties,
but not confer any members dependency (because no assignment, then no preservation).
obj.something.else = 99;
console.log(obj.something.else) // returning a new Proxy()
IMO, it doesn't make sense, or reserved to very specific cases.
Again, it depend of what is your purpose.
Second usage (deep assignment):
Basic not extensible assignment
function proxify(defprop={})
{
return new Proxy(defprop, handler);
};
var handler =
{
get: function(target, property, receiver)
{
if(!(property in target))
target[property] = proxify();
return Reflect.get(target, property, receiver);
},
};
obj.something.else = 99;
console.log(obj.something.else) // returning 99
Extensible to assignment
By using basic chainable proxy, if you try to set a new object (or nested object) you will only trap the root of this new property.
There is no more possible chainning, this is not suitable and not safe.
Remember the following case:
Cyph:
But if the object property is deep nested
obj.something.else.deeper
(Bad way) Assuming this assignment:
var deeper = {toto: "titi"};
obj.something.else = deeper;
console.log(obj.something.else.toto)
// will return "titi"
obj.something.else.toto.something.else = {tutu: "tata"};
// will return a typeError Again
(Good way) To propagate the chain ability
You need to check for the type of value as a true object in the setter trap, and proxify each root properties. The rest of the depth will be converted naturally by the getter trap.
var handler =
{
get: function(target, property, receiver)
{
if(!(property in target))
target[property] = proxify();
return Reflect.get(target, property, receiver);
},
set: function(target, property, value, receiver)
{
// extend proxify to appended nested object
if(({}).toString.call(value) === "[object Object]")
value = deepApply(receiver, property, value);
return Reflect.set(target, property, value, receiver);
},
};
var deepApply = function(receiver,property, data)
{
var proxy = proxify();
var props = Object.keys(data);
var size = props.length;
for(var i = 0; i < size; i++)
{
property = props[i];
proxy[property] = data[property];
}
return proxy;
};
Manage the depth
I invite you to read my actual solution : deepProxy
The level can be auto-defined via the proto declaration
when the object structure is setted. Then you can easily know the current floor and add conditional instructions for each level.
The path of property can be reach from his accessor.

There is a bug in this object extender using hasOwnProperty, I'm uncertain what that bug is or where this extender

The following code is supposed to extend foo with bar, the assignment was to find the "bug" in this snippet but for the life of my I can't seem to find the bug. Is there something I'm missing? Some major case where this code would break when extending objects with other objects?
var foo = {a:1,b:"2",c:[3]}, bar = {d:"3",e:4,f:5.0};
var extend = function (obj, extension) {
if (typeof obj === "object" && typeof extension === "object") {
for (var i in extension) {
if (extension.hasOwnProperty(i) && !obj.hasOwnProperty(i)) {
obj[i] = extension[i];
}
}
return obj;
}
}
var foo_bar = extend(foo,bar);
console.log(foo_bar); //this logs as expected
Maybe it's when you have repeated keys in both objects. Isn't the extending object able to override the extended object's properties?
var foo = {a:1,b:"2",c:[3]}, bar = {c:"3",d:4,e:5.0};
var foo_bar = extend(foo,bar); //will result in {a:1,b:"2",c:"3",d:4,e:5.0};

How to set class name for JavaScript object

I have some test class
TestKlass = (function() {
function TestKlass(value) {
this.value = value != null ? value : 'hello world';
console.log(this.value);
}
return TestKlass;
})();
x = new TestKlass;
x instanceof TestKlass; (gives true)
I have new empty object
y = {}
y instanceof Object
Can I find any ways to set any properties for y, something like this
y.__proto__ = x.__proto__
y.constructor.prototype = x.constructor.prototype
for to have this result
y instanceof TestKlass => true
====================================================
UPD:
So. My main aim - it's to create CLONE function. Now my solution works for me. Please look at this code:
JavaScript JS object clone
Object._clone = function(obj) {
var clone, property, value;
if (!obj || typeof obj !== 'object') {
return obj;
}
clone = typeof obj.pop === 'function' ? [] : {};
clone.__proto__ = obj.__proto__;
for (property in obj) {
if (obj.hasOwnProperty(property)) {
value = obj.property;
if (value && typeof value === 'object') {
clone[property] = Object._clone(value);
} else {
clone[property] = obj[property];
}
}
}
return clone;
};
CoffeeScript JS object clone
# Object clone
Object._clone = (obj) ->
return obj if not obj or typeof(obj) isnt 'object'
clone = if typeof(obj.pop) is 'function' then [] else {}
# deprecated, but need for instanceof method
clone.__proto__ = obj.__proto__
for property of obj
if obj.hasOwnProperty property
# clone properties
value = obj.property
if value and typeof(value) is 'object'
clone[property] = Object._clone(value)
else
clone[property] = obj[property]
clone
Now you can try to do that
A = new TestKlass
B = Object._clone(A)
B instanceof TestKlass => true
It's work fine with Moz FF 13. But I think it's not cross-browser. and proto is deprecated.
I think there is no universal solution. But maybe It's will be helpful for somebody.
Perhaps you should read the following answer first. What you are trying to achieve is really simple. However before I explain let's look at your solutions:
Solution 1
y.__proto__ = x.__proto__;
I wouldn't recommend doing this as the __proto__ property is now deprecated. The above code won't work in Rhino.
Solution 2
y.constructor.prototype = x.constructor.prototype;
This is a very bad solution. The reason is that y.constructor is actually y.__proto__.constructor and since y is an object y.__proto__ is the same as Object.prototype. This means that y.constructor is the same as Object and you're essentially changing the prototype property of Object. This could potentially break other code on your page. I strongly discourage this practice.
Solution 3 (my solution)
What you want to do is simply change the internal [[proto]] property of an object. Since there's no cross platform way to do so we need to employ a hack. A simple solution would be to create a new object with the desired __proto__ property and set getters and setters on it to change the original object. It would be as follows:
function setPrototypeOf(object, prototype) {
var constructor = function () {
for (var key in object) {
if (object.hasOwnProperty(key)) {
(function (key) {
Object.defineProperty(this, key, {
get: function () {
return object[key];
},
set: function (value) {
object[key] = value;
},
enumerable: true
});
}).call(this, key);
}
}
};
constructor.prototype = prototype;
return new constructor;
}
After this all you need to do is:
y = setPrototypeOf(y, TestKlass.prototype);
Here is a working fiddle.
Edit:
The problem with your clone function is that it only clones objects and arrays. You forgot to account for functions which are also passed by reference. Thus when you clone an object which has methods which close over the internal state of the object, the object and its clone will share the same internal state. See the following fiddle:
function Value(value) {
this.get = function () {
alert(value);
};
this.set = function (newValue) {
value = newValue;
};
}
var a = new Value(5);
var b = Object._clone(a);
b.set(10); // setting b to 10 also sets a to 10
a.get(); // alerts 10, should alert 5
There's absolutely no way in JavaScript to clone the internal state of an object so cloning objects and arrays in JavaScript will only work for objects which do not expose closures as methods.
To know more about the problems with cloning objects in JavaScript read this answer. Click on the following link to read John Resig's answer.
obj instanceof SomeConstructor checks whether SomeConstructor is found anywhere in the prototype chain of obj.
If you want inheritance, you need to set the .prototype of FirstConstructor to a newly created SomeConstructor object.
SomeConstructor = function() {}
FirstConstructor = function() {}
FirstConstroctor.prototype = new SomeConstructor();
var y = new FirstConstroctor();
y instanceof FirstConstructor; // true
y instanceof SomeConstructor ; // true, it bubbles from FirstConstructor.__proto__ to SomeConstructor

Categories

Resources