I need to reduce repeated words in a closure compiled js file manually, because i can't use gzip on the compiled js file.
I looked at a few ways to do it, for example I wanted to reduce the word "prototype" so what i did was a reference to the prototype in each object and then used that reference in order to add properties and methods to the object prototype, so the word prototype will be used only once for each object. But it seems that the closure compiler is having trouble with removing not used code this way in some cases, as it keeps methods in the object that are not been used by any object down the prototype chain or by this object itself.
it looks like it can't detect this way if the method is been used by any object down the prototype chain, so it keeps it and making the file size actually larger.
Another thing I tried to do in order to reduce the word "prototype" was using the #nocollapse annotation, but for some reason it breaks the code, the compiled code throws Uncaught ReferenceError about not defined variables and functions when I am trying to use this annotation, or it's just flatten the word, making it been repeated again.
Are there other ways in order to reduce repeated words?
thanks.
Closure compiler has an AliasStrings pass which will help significantly for cases where gzip is not used. It is not enabled nor exposed through a flag. Using it requires a custom build of the compiler.
https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/CompilerOptions.java#L442
Related
I've read a number of questions that state it is unwise to add properties to DOM element objects; and they seem to make a great deal of sense. The best suggestion I came across to accomplish the same end was to use a Weak Map with the DOM node reference as the key.
That led me to wonder about adding properties to function objects. Is that "safe" to do or should another object or map be used for this also. I'm referring to functions on the window object. Can the property names I add clash with names in the function object in the future?
That brings up a related matter I've been trying to understand which is that some claim that the window object is so cluttered up that it ought not to be added to and scripts should be modules now. Modules appears to be more isolated than my limited experience with simple namespaces. Is there anything to be gained through using scripts of type module over just declaring another object and making your functions methods of that object? That object would still be added to the window object.
Thank you.
That led me to wonder about adding properties to function objects. Is that "safe" to do or should another object or map be used for this also. I'm referring to functions on the window object. Can the property names I add clash with names in the function object in the future?
It's not safe in that, if you do it, others could do it too. For example:
// Your code
RegExp.description = 'some description for the constructor!';
setTimeout(() => {
console.log(RegExp.description);
});
// Someone else's code
RegExp.description = "someone else's description";
The only consolation is that it's pretty unlikely for such a thing to happen.
Similarly, it's pretty unlikely for some random English word that one library creates for itself on the window collides with another word that another library creates for itself on the window - but it's not impossible. For that reason
That object would still be added to the window object.
can be seen as slightly less than optimal on huge pages, where collisions are a real possibility.
Is there anything to be gained through using scripts of type module over just declaring another object and making your functions methods of that object?
Yes, see above. If all of your code is in module scripts, there should be no need to put any object onto the window, in most cases. In addition to the above, module scripts often make projects easier to manage because they make all dependencies explicit through the use of import statements. They're also very easily integrated into a build process like Webpack - and build processes allow for all sorts of neat things that aren't easily done otherwise.
Do objects use the property Symbol.iterator, instead of just iterator, to prevent us from overwriting the iterator property on the Object prototype?
If so, are there any other reasons?
Just trying to understand symbols in JS.
If it were just iterator, it could break old code that had objects with methods called iterator. Likewise, whenever the designers of JS want to let developers add other special methods to their objects, they would run the risk of clobbering existing names and breaking existing code.
An alternative is Python’s __double_underscore__ convention where developers are not supposed to defined methods named like this.
I'm in the middle of trying to figure out at least parts of enyo's fantastic dropzone.js. I'm fairly green with JavaScript train of thought and the prototype paradigm. There's a line of code right on the fourth row that I'm wondering what it does and why would one use a line like that. The line looks as follows:
var __slice = [].slice
Have I understood correctly, that this takes the slice function from the array prototype object and just gives it a bit easier way to refer to it? What is the benefit of this approach? And why the double-underscore at the beginning? I read somewhere, that this would be to avoid conflicts in the global scope, but isn't this already avoided by wrapping the whole code in the
(function() { //code here
}).call(this);
construct?
Have I understood correctly, that this takes the slice function from the array prototype object and just gives it a bit easier way to refer to it?
Yes.
What is the benefit of this approach?
__slice is shorter than Array.prototype.slice (which also requires a couple of extra layers of property lookup), and [].slice in theory creates and throws away an object. So having an identifier for it is just saving some typing and the tiniest, tiniest, tiniest bit of runtime performance.
And why the double-underscore at the beginning? I read somewhere, that this would be to avoid conflicts in the global scope, but isn't this already avoided by wrapping the whole code in the ...
Yes, it is already avoided by doing that. In this case, it would just be a convention the author wanted to use, perhaps to indicate that this is his/her shortcut to Array.prototype.slice. The __ has no intrinsic meaning.
There are loads of functions defined in JavaScript built-in object. For example String has slice(),split() and Array has join() and they can be overridden (though it is a bad practice) by simply using
Array.prototype.join = 'test', Then all the array will lose the join() method
However, as a developer of open source project, in what way should we view this potential changes to the prototype? It will become a problem because it is very likely we will use these functions more or less to achieve some functionalities.
In jQuery, it will keep a copy of some of those methods:
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
But only some of the methods are kept safe, if you read through the source code of jQuery you will notice some String methods are called directly on the String object.
Of course we can always keep a copy of all the methods of built-in JavaScript object but it is so messy. Indeed, it also becomes a problem of execution timing. If the program is executed before the prototype is changed, then it's fine. But it will fail if it is vice versa. So I am more interested to know when jQuery or other libraries they decide to keep a copy of some of the methods, what are their philosophy behind the decision?
Thank you.
As a developer of an open source project, the safest and best thing to do is to pretend that the builtin prototypes are frozen. The practice of extending or modifying them is responsible for far more problems than solutions.
If you need a custom join function, just create it so that it takes a string as the first argument.
function join(string, separator) {
// ...
}
This keeps the prototypes clean and stops you from having to worry about references to overwritten methods.
What you're seeing there in the jQuery example is just aliasing. The methods are being assigned to variables to make them easier to use.
There's no way to code defensively around this, because by the time jQuery loads another script could have already modified the builtin prototypes and the original references would be lost.
I have a big object defined in the global scope called global. I would like to dynamically find all the referenced properties under my variable global. That is, all the properties that were accessed during the execution of the code.
I want to do static code analysis to extract all the referenced properties under my variable. I can search for these patterns: global.PROPERTY_NAME AND global[PROPERTY_NAM]. However, what about the complicated cases like these ones
var tmp="PROPERTY_NAME";
global[tmp]
OR
var tmp=global;
tmp.PROPERTY_NAME
and the other ones?
I don't want to get all the variable's properties. I only want a list of the referenced ONES!! the properties that were referenced in my source code only
After your edit:
What you're looking for is JavaScript Proxy objects. Here is a tutorial on how to do this using them.
Proxy objects let you wrap an object and execute a method whenever its properties are accessed. Unfortunately as it currently stands they are not widely supported.
This is currently only way in JavaScript to accomplish this without changing your original global object.
You can turn them on in Chrome by enabling experimental JavaScript in the about:flags tab.
Before your edit:
The feature you're looking for is called reflection, JavaScript supports it well and natively
Here is some code that iterates through an object and gets its properties
for(var prop in global){
if(global.hasOwnProperty(prop)){ //this is to only get its properties and not its prototype's
alert(prop+" => "+global[prop]);
}
}
This is fairly cross-browser. More modern browsers allow you to do this in simpler ways like Object.keys(global) which returns an array containing all its enumerable properties, or Object.getOwnPropertyNames(global) which returns both enumerable and not-enumerable properties.
Due to the dynamic nature of JavaScript you won't achieve that with static code analysis. Think about cases like this:
var prop = document.getElementById('prop').value;
global[prop];
Impossible. The alternative, dynamic analysis, would mean that you modify your global object to log access to its properties, then run the code. This is easily possible in JavaScript but it won't help you either because how would you assure that you have covered every possible access? Especially in a 5 MB JavaScript, there are most likely edge cases that you will oversee.
So, if you can't narrow down your requirement, it won't be possible.