var o = Object.create({inherited: 1}, {
foo: {
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
}
});
o.foo; // "foobar"
I'm having some issues with this. I don't really understand how we're getting the string "foobar" as a result. I'll write my current erroneous understanding of this code, and hopefully someone can explain where I'm mistaken.
o is an object with the property foo.foo corresponds to an object with one property, get. (This seems to be mistaken but I can't see how.)get corresponds to self-invoking anonymous function that returns a function consisting of the one line return closured+'bar';That being said, I would expect o.foo to return an object, and o.foo.get to return a function, and o.foo.get() to return "foobar".
But that's not what's happening, and I don't know why.
Also, separately, why would you ever write something this way? Why write:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
Instead of simply:
get: (function () { // a closure
var closured = 'foo';
return closured+'bar';
})()
What good is done by the extra function layer?
The second parameter to Object.create should be a properties descriptor object. That is an object that describes the properties to be added to the prototype—not literally the object itself. For example:
var o = Object.create({inherited: 1}, {
foo: { /* ... property descriptor object ... */ },
bar: { /* ... property descriptor object ... */ }
});
In the above example we are adding two properties to the prototype of the new object: foo and bar. Each of those properties can be configured in various ways using the descriptor object.
The descriptor object accepts several configuration properties, namely: configurable, enumerable, value, writable, get, set.
In your original example, you effectively configured a getter function for the property foo. If you wish to simply set the value of the property foo, then instead you must create a value property inside the descriptor and add your intended value there (be it actually an object with a property named get if you choose). For example:
var o = Object.create({inherited: 1}, {
foo: {
value: {get: (function () { /* ... code ... */ })() }
}
});
For more detailed information about the property descriptor object see: Object.defineProperty()
There are several things you don't understand right about the code.
var o = Object.create({inherited: 1}, {
foo: {
get: function(){ return 1; }
}
});
console.log(o.foo); // 1
o.foo = 5;
console.log(o.foo); // 1
The second parameter to Object.create describes the object's properties. In this case, the get part is actually a getter, so it describes what happens when the foo property of object o is read.
(function () {
var closure = 'foo';
return function () {
return 'bar';
};
})()
This construct is called an IIFE. It is a function that is called immediately. The advantage of an IIFE is that it creates a local scope, so the closure variable is not visible in the outer scope. This avoids conflicts.
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
// versus:
get: function () { // changed it a bit to be a getter
var closured = 'foo';
return closured+'bar';
}
In the first case, the closured variable is outside of the getter function, while in the second it is inside. Being outside means that its state is not reset everytime the function(getter) is called and it can be available in other functions as well which would all share the same variable. Here is a potential use case:
var namespace = Object.create(null, {
uniqueId : {
get : (function(){
var counter = 0;
return function() {
return counter++;
};
})()
}
});
console.log(namespace.uniqueId); // 0
console.log(namespace.uniqueId); // 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With