I was looking at Twitter's static scripts and noticed that all variables and functions where just 1 character long, why and how do they do this? Has it something to do with performance? If so, why don't they give all elements on their website these kind of short names, maybe 2 characters long instead of 1 to avoid any collisions.
Example:
(function (A) {
A.fn.isScreenNameField = function () {
return this.each(function () {
var M = A(this);
var F = A("#signup_username_url");
var E = A("#screen_name_info");
var D = A("#avail_screenname_check_indicator");
var O;
var C;
var I;
var N = M.val();
var G = N;
var H = N != "";
var Q = /[a-zA-Z0-9_]/;
function K() {
if (H) {
F.html(M.val())
}
}
function L() {
M.trigger("show-info");
E.hide();
D.show()
}
function B() {
E.show();
D.hide()
}
function P() {
G = O;
jQuery.ajax({
type: "GET",
url: "/users/username_available",
data: {
username: O
},
dataType: "json",
success: function (R) {
if (C) {
var S = R.msg;
if (R.valid) {
M.trigger("is-valid");
F.removeClass("invalid").addClass("valid")
} else {
M.trigger("is-invalid", R.msg);
F.addClass("invalid").removeClass("valid")
}
}
},
beforeSend: null,
complete: function () {
clearTimeout(twttr.timeouts.availabilityTimeout);
B()
}
})
}
function J(R) {
O = M.val();
clearTimeout(twttr.timeouts.availabilityTimeout);
C = O.match(Q);
if (!C) {
G = O;
B();
return
}
if (O == G) {
return
}
L();
twttr.timeouts.availabilityTimeout = setTimeout(P, 2000)
}
M.isSignupFormField({
validateWith: function (R) {
if (isBlank(R)) {
return _("Please enter a user name")
} else {
P()
}
},
allowInput: Q
});
M.keyup(function (R) {
if (jQuery.inArray(R.keyCode, [16, 17, 18, 20, 27, 33, 34, 35, 37, 38, 39, 40, 144]) == -1) {
if (M.val() != "") {
H = true
} else {
M.trigger("show-info")
}
K();
J()
}
});
M.bind("value-changed", P);
M.bind("custom-validate", P)
})P
}
})
This script has been "minified", an automated technique of replacing variables with shorter names, without changing functionality. See JSMin, for example. The goal is to reduce download times and bandwidth when sending the script to a client.
They run their scripts through something like http://developer.yahoo.com/yui/compressor/ in order to reduce their size, and therefore the time the need to load.
This is all done in order to decrease the websites load times.
In recent years this topic has become something like a new field, especially due to things like the talks from Steve Stouders: http://stevesouders.com/
Javascript is client-side, so you have to load the script. Less text to download mean better performance, I'd think.
Many javascript projects run their code through a 'minifier' to make the code smaller. This improves the time the browser takes to download the library. Most projects also supply a non-minified version for developers to read:
Example here:
http://docs.jquery.com/Downloading_jQuery#Current_Release
Could be many reasons as to why they do this, to name a common one:
Decrease the filesize of the scripts as alot of people use twitter.
Related
I found this widget online that I am trying to learn how to write in the latest ES6 style. The javascript was minified but I imagine it was originally written in ES6.
So the basic structure of it looks like this:
Some_config = {};
(function() {
var t, e = function(t, e) {
return function() {
return t.apply(e, arguments)
}
},
i = [].slice;
t = function() {
function t() {
this.log = e(this.log, this);
var t;
t = "undefined" != typeof Some_config && null !== Some_config ? Some_config : {},
"undefined" != typeof Some_config && null !== Some_config && this.init(t)
}
return t.prototype.pushMessage = function(t, e) {
return null == e && (e = {}), this.elements.frame.contentWindow.postMessage([t, e], "*")
},
t.prototype.log = function() {
if (this.localOptions.debug)
return console.log("[Debug]", arguments)
},
t.prototype.warn = function(t) {
return console.warn("[Error]", t)
},
t.prototype.init = function(t) {
var e;
try {
this.nextInit(t)
} catch (t) {
e = t, this.warn(e)
}
return this
},
t.prototype.nextInit = function(t) {
console.log('calling nextInit');
},
t
}(), window.SomeApi = new t
}).call(this);
So this javascript runs in a browser, so it looks like it is a immediately invoked but then it calls call(this). What exactly is going on in the last 2 lines?
}(), window.SomeApi = new t
}).call(this);
The style in general looks very foreign to me, is this because it was minified from the original ES6 style?
If this was written as a ES6 class, what would it look like structure wise? I'm hoping it would look cleaner and it would be easier for me to learn/build from.
class SomeApi {
constructor() {
}
log() {
if (this.localOptions.debug)
return console.log("[Debug]", arguments)
}
init(t) {
var e;
try {
this.nextInit(t)
} catch (t) {
e = t, this.warn(e)
}
return this
}
}
I do not think trying to infer the meaning out of minified code is very efficient way to work the original code out.
However, this article could help you
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
What really happens here, is that the outer variable t is being assigned IIFE return value, which is again marked as t. Then the parser moves on and simply assign global variable someApi to the new t. Which is the previous outer t called as constructor.
The following could also be useful to clarify things:
What is the (function() { } )() construct in JavaScript?
https://www.w3schools.com/js/js_function_call.asp
Hi, I'm trying to make my own Pokédex site, but sinds I'm not very good at databases, SQL, PHP and such, I'm doing it in JavaScript, JSON style. While doing this I bumped into a problem: I wanted to refer gen1.gps.Route_1.Exits.South to gen1.gps.Pallet_Town.Title but I didn't know how. Of course I searched the internet for a while first, to find a solution, but I didn't understand it in the context.
var gen1 = {
'gps': {
'Route_1': {
'Title': 'Route 1',
'Exits': {
'North': 0,
'South': // pallet town link here
},
},
'Pallet_Town': {
'Title': 'Pallet Town',
'Exits': {
'North': /* route 1 here */,
'South': 0
}
}
}
}
I expect to be able to call the gen1.gps.Route_1.Exits.South object to get the Title object of gen1.gps.Pallet_Town.
I haven't debugged anything yet so I have no idea what my errors are or will be.
I hope somebody can help me by posting a useful answer.
Need to implement some kind of id system. MySQL takes care of this for you, but like you said, you don't want to have to learn new languages just to see something come to life.
I added IDs to the routes, and then wrote a function to find routes by their IDs. The bottom bit of code (Object.size()) is to get the total number of routes in your gps object. (Same as array.length)
var gen1 = {
'gps': {
'Route_1': {
'Id': 1,
'Title': 'Route 1',
'Exits': {
'North': 0,
'South': 2
},
},
'Pallet_Town': {
'Id': 2,
'Title': 'Pallet Town',
'Exits': {
'North': 1,
'South': 0
}
}
}
};
function getRoute (id)
{
for (var i = 0; i < gen1.gps.size(); i++)
{
if (gen1.gps[i].id == id)
return gen1.gps[i];
}
return false;
}
Object.size = function (obj)
{
var size = 0, key;
for (key in obj)
if (obj.hasOwnProperty (key)) size++;
return size;
};
You can save a lot of work if you create your object dynamically, like this:
var gen1 = {
gps: {}
};
function checkPlace(a) {
if (!gen1.gps[a]) gen1.gps[a] = {};
if (!gen1.gps[a].Title) gen1.gps[a].Title = a.split("_").join(" ");
if (!gen1.gps[a].Exits) gen1.gps[a].Exits = {};
}
function connect(a, b, dir) {
checkPlace(a);
checkPlace(b);
if (dir == "ns") {
gen1.gps[a].Exits.South = gen1.gps[b];
gen1.gps[b].Exits.North = gen1.gps[a];
}
if (dir == "we") {
gen1.gps[a].Exits.East = gen1.gps[b];
gen1.gps[b].Exits.West = gen1.gps[a];
}
}
connect("Route_1", "Pallet_Town", "ns");
console.log(gen1.gps.Route_1.Exits.South.Title);
console.log(gen1.gps);
Explanation:
As a personal project, I'm trying to create my own lightweight version of Dependency Injection for JavaScript - Some would probably disagree with calling this DI because it has no interfaces, but I arrived at the conclusion that interfaces were overkill in JS since we can so easily type check. I have looked at the source of Angular, but I just feel like the complexity there may be overkill for my projects, and I'm interested in attempting my own for a learning experience anyway.
Question:
My question is, fundamentally, is the syntax I'm trying to implement impossible or not?
I'll explain my goal for the syntax, then provide the error and code snippet, and below that I'll post the full code.
Goal for Syntax:
I'd like the creation of a component, and injection of dependencies to work like this, where everything is a component, and anything can be a dependency. I created scope with a string path, using "/scopeName/subScopeName:componentName" to select a scope, so that code users can select the scope while defining the component in a simple way, using a ":" to select a component from the scope.
var JHTML = new Viziion('JHTML');
JHTML.addScope('/generate');
/* ...snip - see full code for the process component - snip ... */
JHTML.addComponent('/generate:init', function (jsonInput, process) {
var html = process(jsonInput);
return html;
}).inject([null, '/generate:process']);
The inject function just takes an array of component paths in the order the component's arguments are expected. null can be used to skip, allowing direct argument input instead, as shown above.
I also have something I call hooks, which are components stored in a certain place, and then there's a function returnUserHandle which will return an object consisting of just the hooks, so all of the functions are hidden in closures, and you can feed the code user just the usable methods, clean and easy, and can produce the final product as a library without the wiring, no need for my DI framework as a dependency. Hopefully that makes sense.
Error:
Right now, running the code (which is a very simple library to generate HTML by parsing a JSON structure) I get the error that process is undefined in the line var html = process(jsonInput);. I was having trouble understanding whether this is a fundamental design problem, or just a bug. Maybe this syntax is not possible, I'm hoping you can tell me.
Code:
Here's the code, and a link to the JS Bin.
/* Dependency Injection Framework - viziion.js */
function Viziion(appName) {
if (typeof appName == 'string') {
var that = this;
this.name = appName;
this.focus = null;
this.scope = {
'/': {
'subScopes': {},
'components': {}
}
};
this.hooks = {};
this.addScope = function(scopeName) {
if (typeof scopeName == 'string') {
var scopeArray = scopeName.split('/');
var scope = that.scope['/'];
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
scope.subScopes[scopeArray[i]] = {
'subScopes': {},
'components': {}
};
}
}
}
} else {
throw 'Scope path must be a string.';
}
return that;
};
this.addComponent = function(componentName, func) {
if (typeof componentName == 'string') {
var scopeArray = componentName.split(':');
if (scopeArray.length == 2) {
var scope = that.scope['/'];
var scopeName = scopeArray[1];
scopeArray = scopeArray[0].split('/');
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if ((i + 1) === scopeArray.length) {
scope.components[scopeName] = func;
that.focus = scope.components[scopeName];
} else if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
throw 'Scope path is invalid.';
}
}
}
} else {
throw 'Path does not include a component.';
}
} else {
throw 'Component path must be a string1.';
}
return that;
};
this.returnComponent = function(componentName, callback) {
if (typeof componentName == 'string') {
var scopeArray = componentName.split(':');
if (scopeArray.length == 2) {
var scope = that.scope['/'];
var scopeName = scopeArray[1];
scopeArray = scopeArray[0].split('/');
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if ((i + 1) === scopeArray.length) {
//console.log('yep1');
//console.log(scope.components[scopeName]);
callback(scope.components[scopeName]);
} else if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
throw 'Scope path is invalid.';
}
}
}
} else {
throw 'Path does not include a component.';
}
} else {
throw 'Component path must be a string2.';
}
};
this.addHook = function(hookName, func) {
if (typeof hookName == 'string') {
that.hooks[hookName] = func;
that.focus = that.hooks[hookName];
} else {
throw 'Hook name must be a string.';
}
return that;
};
this.inject = function(dependencyArray) {
if (dependencyArray) {
var args = [];
for (var i = 0; i < dependencyArray.length; i++) {
if (dependencyArray[i] !== null) {
that.returnComponent(dependencyArray[i], function(dependency) {
args.push(dependency);
});
}
}
console.log(that.focus);
that.focus.apply(null, args);
return that;
}
};
this.returnUserHandle = function() {
return that.hooks;
};
} else {
throw 'Viziion name must be a string.';
}
}
/* JSON HTML Generator - A Simple Library Using Viziion */
var JHTML = new Viziion('JHTML');
JHTML.addScope('/generate');
JHTML.addComponent('/generate:process', function(children) {
var html = [];
var loop = function() {
for (var i = 0; i < children.length; i++) {
if (children[i].tag) {
html.push('<' + tag + '>');
if (children[i].children) {
loop();
}
html.push('</' + tag + '>');
return html;
} else {
throw '[JHTML] Bad syntax: Tag type is not defined on node.';
}
}
};
}).inject();
JHTML.addComponent('/generate:init', function(jsonInput, process) {
console.log(process);
var html = process(jsonInput);
return html;
}).inject([null, '/generate:process']);
JHTML.addHook('generate', function(jsonInput, init) {
var html = init(jsonInput);
return html;
}).inject([null, '/generate:init']);
handle = JHTML.returnUserHandle();
/* HTML Generator Syntax - Client */
var htmlChunk = [{
tag: '!DOCTYPEHTML'
}, {
tag: 'html',
children: [{
tag: 'head',
children: []
}, {
tag: 'body',
children: []
}]
}];
console.log(handle.generate(htmlChunk));
is the syntax I'm trying to implement impossible or not?
It's absolutely possible, and I'm sure with a bit of bugfixing it'd work just fine.
What you're describing is essentially the same as Asynchronous Module Definition (AMD) which is used extensively for handling code dependencies.
Rather than continuing to pursue your own version of the same concept, I recommend that you give requirejs a try and follow the existing standards with your projects.
For a personal challenge, I'm implementing LINQ in JavaScript (well, a set of functions with LINQ-like functionality). However, as of right now, the functions are processing the data immediately; that's correct behavior for some functions (such as Sum or Aggregate), but incorrect for others (such as Select or While).
I'm curious if there's a construct in JavaScript that could get me the same behavior as in .Net, where no real processing happens until the collection is enumerated or a function with immediate execution is used.
Note: I believe this task (implementing LINQ in JS) has already been done. That's not the point. This is a challenge to myself from myself, which is likely to help me increase my understanding of LINQ (and, coincidentally, JS). Beyond personal edification, I'm going to be using LINQ for my job soon, may use JS for my job depending on the needs of individual projects, and I use JS for some things outside of work.
Edit: It seems I've attracted people unfamiliar with LINQ, so I suppose I should give some explanation on that front. LINQ is Language-INtegrated Query, something from .Net. LINQ allows for SQL-like queries on many data sources (including actual SQL relational databases), such as LINQ to Objects, which is what I'm trying to achieve.
One of the features of LINQ is deferred execution on many of the methods. If I have a collection customers and call var query = customers.Where(c => c.Age > 40); (or what it would end up being in JS, var query = customers.Where(function (c) { return c.Age > 40; });), the return value is an interface type, and the actual processing of the collection (returning the subset of the collection containing only customers older than 40) hasn't happened yet. When I use one of the methods without deferred execution (eg, query.First() or query.ToArray()), then all of the deferred processing happens. This could be a chain, such as customers.Where(...).Skip(5).Select(...).OrderBy(...) (each "..." being a function).
The upshot is that code like this:
var collection = [1, 2, 3, 4, 5];
var query = collection.Where(function (n) { return n % 2 == 0; });
collection.push(6);
alert(query.Max());
Would result in "6".
As an addendum, I'm currently implementing this project by prototyping my methods onto both Object and Array, iterating over the elements of this, and skipping any elements which are functions. Something like making an Enumerable class may be superior (and in fact may be required for my deferred execution plan, if something like returning a function or an anonymous object is required), but that's what I've currently got. My functions generally appear as something along these lines:
Object.prototype.Distinct = Array.prototype.Distinct = function (comparer) {
comparer = comparer || function (a, b) { return a == b; };
var result = [];
for (var idx in this) {
var item = this[idx];
if (typeof item == "function") continue;
if (!result.Contains(item, comparer)) result.push(item);
}
return result;
};
Fundamentally what you need to do is return objects from your functions rather than performing operations. The objects you return will contain the code necessary to perform the operations in the future. Consider an example use case:
var myCollection = [];
for(var i = 0; i < 100; i++) { myCollection.push(i); }
var query = Iter(myCollection).Where(function(v) { return v % 2 === 0; })
.Skip(5).Select(function(v) { return v*2; });
var v;
while(v = query.Next()) {
console.log(v);
}
We expect as output:
20
24
28
...
188
192
196
In order to do that we define the methods .Where(), .Skip(), and .Select() to return instances of classes with overridden versions of the .Next() method. Working code that supports this functionality: ( set trace to true to observe that the execution order is lazy)
var trace = false;
function extend(target, src) {
for(var k in src) {
target[k] = src[k];
}
return target;
}
function Iter(wrapThis) {
if(wrapThis.Next) {
return wrapThis;
} else {
return new ArrayIter(wrapThis);
}
}
Iter.prototype = {
constructor: Iter,
Where: function(fn) { return new WhereIter(this, fn); },
Skip: function(count) { return new SkipIter(this, count); },
Select: function(fn) { return new SelectIter(this, fn); }
};
function ArrayIter(arr) {
this.arr = arr.slice();
this.idx = 0;
}
ArrayIter.prototype = extend(Object.create(Iter.prototype),
{
constructor: ArrayIter,
Next: function() {
if(this.idx >= this.arr.length) {
return null;
} else {
return this.arr[this.idx++];
}
}
});
function WhereIter(src, filter) {
this.src = src; this.filter = filter;
}
WhereIter.prototype = extend(Object.create(Iter.prototype), {
constructor: WhereIter,
Next: function() {
var v;
while(true) {
v = this.src.Next();
trace && console.log('Where processing: ' + v);
if(v === null || this.filter.call(this, v)) { break; }
}
return v;
}
});
function SkipIter(src, count) {
this.src = src; this.count = count;
this.skipped = 0;
}
SkipIter.prototype = extend(Object.create(Iter.prototype), {
constructor: SkipIter,
Next: function() {
var v;
while(this.count > this.skipped++) {
v = this.src.Next();
trace && console.log('Skip processing: ' + v);
if(v === null) { return v; }
}
return this.src.Next();
}
});
function SelectIter(src, fn) {
this.src = src; this.fn = fn;
}
SelectIter.prototype = extend(Object.create(Iter.prototype), {
constructor: SelectIter,
Next: function() {
var v = this.src.Next();
trace && console.log('Select processing: ' + v);
if(v === null) { return null; }
return this.fn.call(this, v);
}
});
var myCollection = [];
for(var i = 0; i < 100; i++) {
myCollection.push(i);
}
var query = Iter(myCollection).Where(function(v) { return v % 2 === 0; })
.Skip(5).Select(function(v) { return v*2; });
var v;
while(v = query.Next()) {
console.log(v);
}
You also may want to look into "string lambdas" to make your queries much more readable. That would allow you to say "v*2" instead of function(v) { return v*2; }
I am not entirely clear on what exactly you wish to do, but I think what you should look into is the defineProperty method. What you would probably wish to do is then to redefine the .length property and execute the code only once it's read. Or if you want to do it only once the property itself is read do it at that point. Not sure how LINQ works or even what it is, so that's why I am a bit vague. Either way, with defineProperty you can do something like
Object.defineProperty(o, "a", { get : function(){return 1;});
Allowing you to do actions only once the property is accessed (and you can do a lot more than that as well).
Many websites, like Catch.com, depend on JavaScript heavily. Catch.com for example, when save the webpage, a javascript file: catchapp.js is downloaded, but it's content begins with strange codes, like:
function e(a) { throw a; }
var i = void 0, j = !0, k = null, m = !1;
function ba() { return function (a) { return a } }
function ca() { return function () { } }
function da(a) { return function (b) { this[a] = b } }
So do they use some tools to change their js files before release?
They use JavaScript minification tools like jscompress. This will reduce the filesize, speed up the user's download and reduce bandwidth costs. It also works as code obfuscation.