Reputation: 52551
I want to have my cake and eat it too: I want to have a method that returns this
for chaining when it is bound to an object but returns undefined
when it is called with a null|undefined scope. This seems to work fine but if you put it into JSLint then you get a Strict Violation errors. I don't need to use strict mode, but it seems like this should be possible and it works (open the console). Is this okay and/or how else could you accomplish this effect?
var o = {}; // or some pre-existing module
o.meth = (function (undefined) {
// contrived example where you'd want to be able to locally
// access `meth` even if the outer `o.meth` was overwritten
'use strict';
var hash = Object.create(null); // "object" with no properties
// global ref - or `null` where strict mode works
var cantTouchThis = (function () {
return this;
}).call(null);
function meth (k, v) {
var n;
if (typeof k == 'object') { // set multi
for (n in k) {
meth(n, k[n]);
}
} else {
if (v === undefined) { return hash[k]; } // get
hash[k] = v; // set
}
if (this == cantTouchThis) { return; }
return this;
}
return meth;
}());
And if you look in the console:
var localM = o.meth; // now scopeless
console.log( o.meth('key', 'val') ); // should return `o`
console.log( localM('key', 'val') ); // should return `undefined`
Upvotes: 2
Views: 403
Reputation: 52551
To be redundantly safe, I ended up using a local function for "grounding" scope resolution:
var gnd = (function () {
var globe = this || window;
return function (o) {
// for grounding (securing) scope
return o == null || o === globe ? 0 : o;
};
}());
See usage in the source here.
Upvotes: 0
Reputation: 39188
This will almost do what you want.
dontTouchThis
will be null
in environment that supports "use strict" directive, and will reference global object in those that don't support it.
First of all, you can replace that .call(null)
chunk with just (function(){return this})()
; it will have more or less the same effect.
Second, don't forget that there are 4 ways function can be called, when it comes to this
value: as a method, as a standalone (baseless) function, via call/apply, and with new
operator. This means that:
new (o.meth)
will return o
o.meth.call(o2, ...)
will return o2
o.meth.call(null, ...)
will return undefined
Finally, if someone aliases meth
to a global variable, then in strict-mode-supporting environment meth()
will return global object, not undefined
since cantTouchThis
(being null
) won't be equal to this
(which will reference global object).
// in global scope
var meth = o.meth;
meth(...); // `this` references global object, will return global object
(function() {
// in local scope
var meth = o.meth;
meth(...); // `this` is `undefined`, will return `undefined`
})();
Upvotes: 1