It looks like your goal is for newClass
to return an object that uses Runner
as its prototype and has param
as a property. There's a dramatically simpler way to do that; see comments:
var newClass = function(obj) {
// Create an object using `obj` as its prototype
var nf = Object.create(obj);
// Give it a `param` property
nf.param = "the param";
// Return it
return nf;
};
var Runner = {
run: function() {
// Note the use of `this `on the next line, to access
// the property in the instance
console.log("calling method run " + this.param);
}
};
var nf = newClass(Runner);
nf.run();
Object.create
was added in ES5 (in 2009) and so exists in just about any JavaScript engine that's vaguely recent (so, not the one in IE8); the one-argument version of it above can be shimmed with code very similar to that in your question, see MDN.
On a fully ES5-compliant JavaScript engine, you can use the second argument of Object.create
(which cannot be shimmed/polyfilled) to control the enumerability, writability, and configurability of the property:
var newClass = function(obj) {
// Create and return an object using `obj` as its prototype,
// with a `param` property:
return Object.create(obj, {
param: {
value: "the param"
}
});
};
In that example, param
will be non-enumerable, read-only, and not configurable.
Side note: I wouldn't call a function that creates new objects newClass
, just FWIW. :-)
In a comment you've said:
My goal is to generate a private variable, only accessible from the inside of Runner. In your example, param is accessible from the outside.
If so, you can't do it with Runner
being defined outside the newClass
function because, by definition, that's...outside the newClass
function.
What you can do is define run
within newClass
, perhaps having it turn around and call a function on Runner
that accepts the param as an argument:
var newClass = function(obj) {
// The private variable
var param = "the param";
// Create an object using `obj` as its prototype
var nf = Object.create(obj);
// Create `run`
nf.run = function() {
this.runWithParam(param)
};
// Return it
return nf;
};
var Runner = {
runWithParam: function(param) {
console.log("calling method runWithParam " + param);
}
};
var nf = newClass(Runner);
nf.run();
...or possibly don't use Runner
as the prototype at all:
var newClass = function(runner) {
// The private variable
var param = "the param";
// Create an object with `run` on it
var nf = {
run: function() {
return runner.runWithParam(param);
}
};
// Return it
return nf;
};
var Runner = {
runWithParam: function(param) {
console.log("calling method runWithParam " + param);
}
};
var nf = newClass(Runner);
nf.run();