I am new to javascript and I've been wondering about something. Is there an accepted way I should be listing my object properties?
To be specific, I have been writing code where an object is created without any initial properties and adding them on as the code runs.
Example:
Game = {};
Game.x = 0;
...Code code code
Game.thing = function () {
Game.variable = 30;
}
As you can see, my Game object is just slowly gathering properties as my code runs on. Is this acceptable? Or should I be listing out all the properties I will be using at the beginning in my Game object initialization? Thanks.
You can do this:
var Game = { // DON'T FORGET var !!!!!
x: 0,
something: some_value,
thing: function() {
this.variable = 30;
}
};
What you're doing in your code is not really wrong (except don't forget var!!). It's a matter of style and intent. The above code (well the part in the curly braces) is called an "object literal", and it's a way of creating an object as a JavaScript value on the fly. It's very useful, but it's not necessarily better than other ways of building an object.
edit
Note that according to this article when an object (in V8 at least, though I suspect other runtimes are likely to have similar behavior) starts looking like it's being used like a map, then it internally is optimized for that purpose. After that point, for ... in loops over the object will no longer be candidates for optimization. You can (I think) still use Object.keys() to do such iterations, and overall it's probably a net benefit, but it might be the case that objects that experience a lot of property creation fall into that situation.
It really depends on your application. If you have all of the data you want to put in your object when you create it, use an object literal:
var Game = {
x: 0,
thing = function () {
this.variable = 30;
}
}
However, there may be instances where you want to add to your newly created object as you go. This is common when namespacing (which it seems like you're trying to do).
I would start with something like this:
var Game = Game || {};
That way, you make sure you aren't colliding with another object. Then go from there, by adding your properties and methods. A common approach is to create a closure and assign new methods from within that closure.
(function() {
var foo = function () {
... stuff ...
}
Game.foo = foo;
})();
That way, you don't run the risk of accidentally creating any global variables. :)
Related
Having read this article https://www.toptal.com/javascript/es6-class-chaos-keeps-js-developer-up and subsequently "JavaScript: The Good Parts", I shall henceforth commit to becoming a better JavaScript developer. However, one question remained for me. I usually implemented methods like this:
function MyClass(){
this.myData = 43;
this.getDataFromObject = function(){
return this.myData;
}
}
MyClass.prototype.getDataFromPrototype = function(){
return this.myData;
}
var myObject = new MyClass();
console.log(myObject.getDataFromObject());
console.log(myObject.getDataFromPrototype());
My assumption that underlies this whole post is that getDataFromObject is faster (during call, not during object creation) because it saves an indirection to the prototype but it is also less memory-efficient because every object gets an own instance of the function object. If that is already wrong, please correct me and you can probably stop reading here.
Else: Both article and book recommend a style like this:
function secretFactory() {
const secret = "Favor composition over inheritance [...]!"
const spillTheBeans = () => console.log(secret)
return {
spillTheBeans
}
}
const leaker = secretFactory()
leaker.spillTheBeans()
(quote from the article, the book didn't have ES6 yet but the ideas are similar)
My issue is this:
const leaker1 = secretFactory()
const leaker2 = secretFactory()
console.log(leaker1.spillTheBeans === leaker2.spillTheBeans) // false
Do I not mostly want to avoid that every object gets an own instance of every method? It might be insignificant here but if spillTheBeans is more complicated and I create a bazillion objects, each with twelvetythousand other methods?
If so, what is the "goot parts"-solution? My assumption would be:
const spillStaticBeans = () => console.log("Tabs rule!")
const spillInstanceBeans = (beans) => console.log(beans)
function secretFactory() {
const secret = "Favor composition over inheritance [...]!"
return{
spillStaticBeans,
spillInstanceBeans: () => spillInstanceBeans(secret)
}
}
const leaker1 = secretFactory()
const leaker2 = secretFactory()
leaker1.spillStaticBeans()
leaker2.spillInstanceBeans()
console.log(leaker1.spillStaticBeans === leaker2.spillStaticBeans) // true
console.log(leaker1.spillInstanceBeans === leaker2.spillInstanceBeans) // false
The spillInstanceBeans method is still different because each instance needs its own closure but at least they just wrap a reference to the same function object which contains all the expensiveness.
But now I have to write every method name two to three times. Worse, I clutter the namespace with public spillStaticBeans and spillInstanceBeans functions. In order to mitigate the latter, I could write a meta factory module:
const secretFactory = (function(){
const spillStaticBeans = () => console.log("Tabs rule!")
const spillInstanceBeans = (beans) => console.log(beans)
return function() {
const secret = "Favor composition over inheritance [...]!"
return{
spillStaticBeans,
spillInstanceBeans: () => spillInstanceBeans(secret)
}
}
}())
This can be used the same way as before but now the methods are hidden in a closure. However, it gets a bit confusing. Using ES6 modules, I could also leave them in module scope and just not export them. But is this the way to go?
Or am I mistaken in general and JavaScript's internal function representation takes care of all this and there is not actually a problem?
My assumption that underlies this whole post is that getDataFromObject is faster to call than getDataFromPrototype because it saves an indirection to the prototype
No. Engines are very good at optimising the prototype indirection. The instance.getDataFromPrototype always resolves to the same method for instances of the same class, and engines can take advantage of that. See this article for details.
Do I not mostly want to avoid that every object gets an own instance of every method? It might be insignificant here
Yes. In most of the cases, it actually is insignificant. So write your objects with methods using whatever style you prefer. Only if you actually measure a performance bottleneck, reconsider the cases where you are creating many instances.
Using ES6 modules, I could also leave them in module scope and just not export them. But is this the way to go?
Yes, that's a sensible solution. However, there's no good reason to extract spillInstanceBeans to the static scope, just leave it where it was - you have to create a closure over the secret anyway.
The spillInstanceBeans method is still different because each instance needs its own closure but at least they just wrap a reference to the same function object which contains all the expensiveness.
It should be noted that you're just replicating the way the JavaScript VM works internally: a function like spillTheBeans is compiled only once where it occurs in the source code even if it has free variables like secret. In SpiderMonkey for example, the result is called a »proto-function« (not to be confused with prototype). These are internal to the VM and cannot be accessed from JavaScript.
At runtime, function objects are created by binding the free variables of proto-functions to (a part of) the current scope, pretty much like your spillInstanceBeans example.
Saying that, it's true that using closures instead of prototype methods and this creates more function objects overall – the robustness gained from true privacy and read-only properties might make it worthwhile. The proposed style focuses more on objects rather than classes, so a different design could emerge that cannot be compared directly to a class-based design.
As Bergi says, measure and reconsider if performance is more important in (some part of) your code.
I find it strange that all WebGL constants are defined as members of the rendering context. This means that if the context is wrapped in some library, accessing those constants becomes problematic.
Is there any reason why I can't define them all explicitly? Or, if they are implementation defined, maybe the first time a context is created, write all enum values to some global object?
Basically, instead of writing new renderer.Texture(renderer.gl.TEXTURE_2D) or new renderer.Texture("TEXTURE_2D"), I want to write something like new renderer.Texture(WebGL.TEXTURE_2D).
You can access them using WebGLRenderingContext and WebGL2RenderingContext without creating an instance of a context. For example:
console.log(WebGLRenderingContext.TEXTURE_2D); // 3553
you are free to define them as your own constants. In fact it may make your code faster
const TEXTURE_2D = 0x0DE1
...
gl.bindTexture(TEXTURE_2D, someTexture);
Is perfectly fine. And, if that code is run through a modern JavaScript compressor it will get turned into this
gl.bindTexture(0x0DE1, someTexture);
Which will arguably be faster. Faster then gl.TEXTURE_2D because using gl.TEXTURE_2D the JavaScript engine has to always check that someone didn't assign gl.TEXTURE_2D to something else. Faster than TEXTURE_2D because even a const variable represents something being created where as 0x0DE1 definitely does not.
Just because I'll probably get some questions later, my point above about speed is the JavaScript engine has to check every single time you call
gl.bindTexture(gl.TEXTURE2D, ...)
That someone somewhere didn't do
gl.TEXTURE_2D = 123
or make a property getter
Object.defineProperty(gl, 'TEXTURE_2D', {
enumerable: true,
writable: false,
get() {
console.log('TEXTURE_2D was accessed at', (new Error()).stack));
return 0xDE1;
}
});
The JavaScript engine can't assume the the TEXTURE_2D property was not changed. It has to check every time.
As for const there may or may not be a general speed difference but for example if we make a function that returns a function like this
function makeFuncThatReturnsValue(value) {
const v = value;
return function() {
return v;
}
}
We can see that every time we call makeFuncThatReturnsValue a new v will be created and captured in the closure.
Just using a literal directly won't have that issue, nothing will be created. Of course you don't want to use the literal directly, magic numbers are bad, but if you compile your JavaScript with a modern compressor it will swap any consts for literals where appropriate.
Running an example through Google's closure compiler
Code:
const w = {
TEXTURE_2D: 0x0DE1,
};
gl.bindTexture(w.TEXTURE_2D, null);
Result:
gl.bindTexture(3553,null);
So I'm working on a sort of JavaScript framework, just some utility things for myself to use in future projects, and I want to make a data binding system.
The first method I used was objects, and the code would just loop through the specified html element and look for occurences of {{key}} in the markup and then look for that key in the object and replace it that way in the HTML.
For example, if you had <div>{{name}} is a cool guy</div> in the HTML and had {name:"joseph"} in the JS then the final product would be displayed on screen as 'joseph is a cool guy'.
However, I decided later to change my method and instead the framework would except a function. So instead of {name:"joseph"} you would give it function(){ var name = "joseph" }.
This obviously looks better and gives a lot better functionality.
I changed the processing function so instead of looking for the key/value pair to replace the {{key}}, it just uses eval on the variable to gets its value.
My problem lies here: How do I run my search/replace code INSIDE the scope of the function the user passes.
If the user defines variables within that function, their values will not be available anywhere else due to scope issues.
I've tried using Function.toString() to actually modify the source code of the function, but nothing's working and it's all very complicated.
(The issues are not due to the actual solution, I think that Function.toString() might work, but due to my implementation. I keep getting errors)
So... What is the best way to run arbitrary code in the scope of another function?
Critera:
Obviously, I can't modify the function because the user is passing it in. (you can't just tell me to add the search/replace code to the bottom of the function)
The variables must stay in the local scope of the function. (no cheating by using window.name = "joseph" or anything)
I am also aware of how terrible eval is so any suggestions as to get it to work are greatly appreciated. Thanks!
Code:
function process(html) {
var vars = html.match( /({{)[^{}]*(}})/g )
// vars = ['{{variable}}', '{{anotherVariable}}']
var names = vars.map( function(x){ return x.replace("{{", "").replace("}}", "") } )
// names = ['variable', 'anotherVariable]
obj = {}
for (var i = 0; i < names.length; i++) {
obj[names[i]] = eval(names[i])
}
for (var p in obj) {
html = html.replace(new RegExp('{{'+p+'}}','g'), obj[p]);
}
return html
}
You should go back to your first method with the object, it's much better. You can still pass a function, but the function should return an object:
function () {
return { name: 'joseph' }
}
ap = Array.prototype,
aps = ap.slice,
apsp = ap.splice,
I often see code like above in different frameworks. What are the benefits of this?
Why not use it directly?
When used exactly as you've shown, the primary reason is to reduce the amount of typing in code that will heavily utilize the referenced method or object. Further, this can have the effect of reducing the overall size of a script. Consider:
Array.prototype.someFunction1 = function () { /*someFunction1 */ };
Array.prototype.someFunction2 = function () { /*someFunction2 */ };
Array.prototype.someFunction3 = function () { /*someFunction3 */ };
Array.prototype.someFunction4 = function () { /*someFunction4 */ };
... (284 characters) versus:
var ap = Array.prototype;
ap.someFunction1 = function () { /*someFunction1 */ };
ap.someFunction2 = function () { /*someFunction2 */ };
ap.someFunction3 = function () { /*someFunction3 */ };
ap.someFunction4 = function () { /*someFunction4 */ };
... which has 261 characters. Trivial, yes, but on a large scale this can make enough of a difference to be worthwhile in distributed code (think Google-hosted jQuery).
Sometimes, however, this is done to preserve scope through a closure:
var self = this;
this.someProperty = 5;
var myDiv = document.createElement('div');
myDiv.addEventListener('mousedown', function(e) { alert(self.someProperty); }, false);
Several benefits:
Faster at run-time (fewer lookups to get the final result)
Smaller code before minification
Easier to reduce even more with minification
Less typing when coding
One should note that I think it makes the code less readable to people not already familiar with the code or its conventions because the code isn't as self documenting. Everyone knows what Array.prototype.splice is but strangers don't know what aps is until they study the code, track down its definition and remember what it is.
I was asked in a comment to explain the fewer lookups issue:
For the interpreter to resolve Array.prototype.splice, it has to do the following:
Look in the local scope for the Array name. It doesn't find it.
Look in any closures (e.g. parent scope) for the Array name. It doesn't find it.
Look in the global scope for the Array name. It finds it.
On the Array object, look for the prototype property.
On the prototype property, look for the splice property and now it finally has the function it needs.
For the interpreter to resolve aps, it has to do this:
Look in the local scope for the aps name. It finds it and not it has the function it needs.
The pre-assignment to aps has essentially pre-done the lookups so that they are already resolved at runtime. This removes some flexibility because if the value of the splice or prototype properties are changed, the variable aps won't reflect that change, but if you know they aren't supposed to change (something the run-time interpreter doesn't know), then you can take advantage of this shortcut.
One functional reason this pattern would exist would be to protect against other javascript code changing the meaning of the particular methods. Essentially protecting from code like the following
Array.prototype.splice = function() {
// This is evil
};
The other more likely though is the developer simply didn't want to type Array.prototype.splice and prefered a shorter version like apsp.
There are two benefits.
a is easier to minify then Array.prototype.slice
a is a single lookup where Array.prototype.slice is multiple look ups
So basically they are both micro optimisations. Which are valuable in libraries because libraries care about being as efficient as possible
I am working on making all of our JS code pass through jslint, sometimes with a lot of tweaking with the options to get legacy code pass for now on with the intention to fix it properly later.
There is one thing that jslint complains about that I do not have a workround for. That is when using constructs like this, we get the error 'Don't make functions within a loop.'
for (prop in newObject) {
// Check if we're overwriting an existing function
if (typeof newObject[prop] === "function" && typeof _super[prop] === "function" &&
fnTest.test(newObject[prop])) {
prototype[prop] = (function(name, func) {
return function() {
var result, old_super;
old_super = this._super;
this._super = _super[name];
result = func.apply(this, arguments);
this._super = old_super;
return result;
};
})(prop, newObject[prop]);
}
}
This loop is part of a JS implementation of classical inheritance where classes that extend existing classes retain the super property of the extended class when invoking a member of the extended class.
Just to clarify, the implementation above is inspired by this blog post by John Resig.
But we also have other instances of functions created within a loop.
The only workaround so far is to exclude these JS files from jslint, but we would like to use jslint for code validation and syntax checking as part of our continuous integration and build workflow.
Is there a better way to implement functionality like this or is there a way to tweak code like this through jslint?
Douglas Crockford has a new idiomatic way of achieving the above - his old technique was to use an inner function to bind the variables, but the new technique uses a function maker. See slide 74 in the slides to his "Function the Ultimate" talk. [This slideshare no longer exists]
For the lazy, here is the code:
function make_handler(div_id) {
return function () {
alert(div_id);
};
}
for (i ...) {
div_id = divs[i].id;
divs[i].onclick = make_handler(div_id);
}
(I just stumbled on this questions many months after it was posted...)
If you make a function in a loop, an instance of a function is created for each iteration of the loop. Unless the function that is being made is in fact different for each iteration, then use the method of putting the function generator outside the loop -- doing so isn't just Crockery, it lets others who read your code know that this was your intent.
If the function is actually the same function being assigned to different values in an iteration (or objects produced in an iteration), then instead you need to assign the function to a named variable, and use that singular instance of the function in assignment within the loop:
handler = function (div_id) {
return function() { alert(div_id); }
}
for (i ...) {
div_id = divs[i].id;
divs[i].onclick = handler(div_id);
}
Greater commentary/discussion about this was made by others smarter than me when I posed a similar question here on Stack Overflow:
JSlint error 'Don't make functions within a loop.' leads to question about Javascript itself
As for JSLint:
Yes, it is dogmatic and idiomatic. That said, it is usually "right" -- I discover that many many people who vocalize negatively about JSLint actually don't understand (the subtleties of) Javascript, which are many and obtuse.
Literally, get around the problem by doing the following:
Create a .jshintrc file
Add the following line to your .jshintrc file
{"loopfunc" : true, // tolerate functions being defined in loops }
JSLint is only a guide, you don't always have to adhere to the rules. The thing is, you're not creating functions in a loop in the sense that it's referring to. You only create your classes once in your application, not over and over again.
If you are using JQuery, you might want to do something like this in a loop:
for (var i = 0; i < 100; i++) {
$("#button").click(function() {
alert(i);
});
}
To satisfy JSLint, one way to work around this is (in JQuery 1.4.3+) to use the additional handler data argument to .click():
function new_function(e) {
var data = e.data; // from handler
alert(data); // do whatever
}
for (var i = 0; i < 100; i++) {
$("#button").click(i, new_function);
}
Just move your:
(function (name, func) {...})()
block out of the loop and assign it to a variable, like:
var makeFn = function(name, func){...};
Then in the loop have:
prototype[prop] = makeFn(...)