Best javascript questions in October 2011

How can you trigger the "What the hell is this?" JSLint message?

22 votes

JSLint has some interesting messages, such as eval is evil. when you use an eval statement, and Weird relation. when comparing two literals, e.g. 1 == 2.

I was looking through a list of the JSLint messages, and noticed this one at the bottom of the list:

What the hell is this?

I looked through the JSLint source and found this code:

if (stack.length === 0) {
    error("What the hell is this?", nexttoken);
}

I have been trying for a while, unsuccessfully, to write code that triggers this. Nothing I have read about JSLint talks about this error message, why it exists, or what causes it. I've briefly inspected the code, but I can't really understand what the stack is, how is is populated or what could cause it to be empty.

Can somebody write a code sample that will cause JSLint to scream What the hell is this? or explain howwhat prevents this from happening?

It looks a lot like a "can't happen" check (a form of defensive programming). If so, there might not be any way to trigger it in practice.

What does Dart's output look like?

20 votes

Dart, Google's new web language, says it supports outputting to JavaScript.

What does a simple conversion look like?

main() {
      print('Hello, Dart!');
}

is converted into:

var e;function f(a,b){if(b>=0&&b<a.length)return b;h(aa(b))};Boolean.D=function(a){return typeof a=="boolean"||a instanceof Boolean};var i={},ba={};function ca(a,b){return function(c,d){return a.call(void 0,b,c,d)}}function j(a,b,c){return function(d,g,m){return a.call(b,c,d,g,m)}}function da(a,b,c){return function(d,g,m,p){return a.call(b,c,d,g,m,p)}}function ea(a,b){var c=fa;return function(d,g,m){return c.call(void 0,a,b,d,g,m)}}function ga(a,b){if(a.prototype.__proto__)a.prototype.__proto__=b.prototype;else{var c=function(){};c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a}}
function k(a){if(!(typeof a=="function"?a():a))throw a=Error("Assertion failed. "),Error.captureStackTrace&&Error.captureStackTrace(a),a;}function ha(a,b){return typeof a=="number"&&typeof b=="number"?a+b:a.Pa(b)}function ia(a){a/=4;return a<0?Math.ceil(a):Math.floor(a)}function l(a,b){return a===void 0?b===void 0:typeof a=="number"&&typeof b=="number"?a==b:a.U(b)}function h(a){a&&typeof a=="object"&&Error.captureStackTrace&&Error.captureStackTrace(a);throw a;}
function n(){var a=new o;a.f=ja();Object.g.call(a);a.Ya="";a.Sa="";a.ia=[];Object.d.call(a);h(a)}var q={a:0};function r(a){if(a===void 0)return"";if(typeof a==="number")return"n"+a;if(typeof a==="boolean")return"b"+(a?1:0);if(typeof a==="string"){var a=ka+a,b=la[a];b||(b="s"+ ++ma,la[a]=b);return b}if(typeof a==="function")throw"a function is not a constant expression";a=a.ab;if(a===void 0)throw"internal error: reference to non-canonical constant";return a}var ka=":",ma=0,la={},na={};
function t(a,b){var c;if(a instanceof Array){c=[];for(var d=a.length-1;d>=0;d--)c.push(r(a[d]));c="a"+c.join(",")}else if(a&&a.Ma){c=oa();c.n("m");for(var d=true,g=pa(a).oa(0,q);g.aa(0,q);){var m=g.pa(0,q);d?d=false:c.n(",");c.n(r(m));c.n(",");c.n(qa(a.L(m)))}c=c.o(0,q)}else c="o"+a.t();if(b!=null){c+="<";for(d=b.length-1;d>=0;d--)c+=b[d],c+=",";c+=">"}d=ka+c;g=na[d];if(g!=null)return g;a.ab=c;return na[d]=a};var u=null,v=[],w=this,x=typeof w.importScripts!="undefined",ra=x||typeof w.Worker!="undefined",y=0,z=ra,A=false;function sa(a,b,c,d,g){if(a==y){if(a=ta.get(b))(c=a.Da.get(c))&&ua(c,a,d,g)}else(x?B:va.get(a)).postMessage({$:"message",qb:a,lb:b,mb:c,ea:d,ga:g})}function ua(a,b,c,d){wa(b,function(){var b=z||A?xa(c):c,m=z||A?xa(d):d;if(a.V!=null){var p;var C=a.V;if(C===ba)throw"circular initialization";C!==i?p=C:(a.V=ba,a.V=void 0);p(2,q,b,m)}ya()})}function za(){this.map={};this.a=0}
function Ba(a,b,c){if(a.map[b])throw Error("Registry: Elements must be registered only once.");a.map[b]=c;a.a++}function Ca(a){var b=va;a in b.map&&(delete b.map[a],b.a--)}za.prototype.get=function(a){return this.map[a]};var va=new za,ta=new za,Da=false;x&&(Da=function(a){B.postMessage({$:"print",ea:a})});
function Ea(a,b){var c=b.data;switch(c.$){case "start":y=c.id;var d=w[c.$a](),g=c.ga;wa(new Fa,function(){var a=z||A?xa(g):g,b=Ga(),c;0!=q.a&&n();c=Ha.prototype.Fa.call(b);if(u.w==null||u.w.J())Ia.call(a,"spawned",c);else{c={message:"spawned",ga:c};var s=t(D([],Array.h()),[""]),J;J={};if(u.w==null){var Aa=Ja();u.w=Aa}J.Ga=s.length;Aa=j(Ka,void 0,J);for(s=s.oa(0,q);s.aa(0,q);)La(s.pa(0,q),Aa);J.result=Ma();u.w.S(ca(Na,J));ya();La(J.result,j(Oa,a,c))}d.Db(b)});Pa();break;case "spawn-worker":Qa(c.$a,
c.Jb);break;case "message":sa(c.qb,c.lb,c.mb,c.ea,c.ga);Pa();break;case "close":Ca(a.id);a.terminate();Pa();break;case "print":Ra(c.ea);break;case "error":throw c.ea;}}if(ra)w.onmessage=function(a){Ea(B,a)};var B=new function(){this.id=0};B.postMessage=function(a){w.postMessage(a)};var Sa=1;function Fa(){this.id=Sa++;this.nb={};this.nb.Ib=Math.random()*268435455>>>0;this.Da=new za;Ta(this,function(){for(var a=0,b=v.length;a<b;a++)v[a]()})}function Ta(a,b){var c=u;u=a;try{b()}finally{u=c}}var Ua=[];
function Va(a,b){this.kb=a;this.hb=b}function wa(a,b){Ua.push(new Va(a,b))}var Wa=y+1,Xa;if(!ra||x)Xa=null;else{var Ya=document.getElementsByTagName("script"),Za=Ya[Ya.length-1],$a=Za.src;if(!$a)$a="FIXME:5407062_"+Math.random().toString(),Za.src=$a;Xa=$a}function Qa(a,b){var c=new Worker(Xa);c.onmessage=function(a){Ea(c,a)};var d=Wa++;c.id=d;Ba(va,d,c);c.postMessage({$:"start",id:d,ga:b,$a:a})}
function Ia(a,b){if(b!==void 0&&!(b instanceof ab))throw"SendPort::send: Illegal replyTo type.";a=z||A?bb(a):cb(a);b=z||A?bb(b):cb(b);sa(this.H,this.F,this.G,a,b)}function db(){var a;Ua.length!=0?(a=Ua[0],Ua.splice(0,1)):a=void 0;return a?(Ta(a.kb,a.hb),true):(x&&ta.a===0&&B.postMessage({$:"close"}),false)}function eb(){if(typeof window!="undefined"&&window.setTimeout)(function b(){db()&&window.setTimeout(b,0)})();else for(;;)if(!db())break}
function Pa(){if(x)try{eb()}catch(a){B.postMessage({$:"error",ea:""+a})}else eb()};Number.D=function(a){return typeof a=="number"||a instanceof Number};Object.D=function(){return true};function fb(a){Da?Da(a):this.console?this.console.log(a):this.write&&(this.write(a),this.write("\n"))};function E(a,b,c){this.c=a;this.pb=b?b:a;this.i=c;this.b={};this.b[a]=this;a!=F("Object")&&(this.b[F("Object")]=G)}var gb={};E.prototype.q=[];E.prototype.toString=function(){return this.pb};E.prototype.ya=function(a){return a==null?this===G||this===H:this.ca(hb(a))};function ib(a,b){return a.hasOwnProperty(b)?a[b]:null}
E.prototype.ca=function(a){if(a===this||a===H)return true;a=ib(a.b,this.c);if(a==null)return false;if(a.i&&this.i)for(var b=this.i.length-1;b>=0;b--)if(!this.i[b].ca(a.i[b]))return false;return true};function jb(a){if(a instanceof Array)return Array.h();switch(typeof a){case "string":return String.h();case "number":return Number.h();case "boolean":return Boolean.h()}return kb}
function I(a,b,c){if(a==F("Object"))return G;var d=lb(a,c),g=ib(gb,d);if(g)return g;a=lb(a);g=new E(a,d,c);gb[d]=g;b&&b(g,c);return g}function lb(a,b){var c=a;b&&(c+="<"+b.join(",")+">");return c}function hb(a){return a.f?a.f:jb(a)}function D(a,b){a.f=b;return a}function K(a,b){if(a)if(a.length>b)return a[b];else throw Error("Missing type arg");return H}function L(a,b){var c=ib(hb(a).b,b);if(!c)throw Error("internal error: can not find "+b+" in "+JSON.stringify(a));return c.i}var G=new E(F("Object"));
G.ya=function(){return true};G.ca=function(){return true};var H=new E(F("Dynamic"));H.ya=function(){return true};H.ca=function(){return true};var kb=new E(F("::"));kb.ya=function(){return true};kb.ca=function(){return true};D(Function.prototype,I(F("Function$Dart")));function F(a){return"cls:"+a};String.D=function(a){return typeof a=="string"||a instanceof String};function mb(a){if(!(a instanceof Array)){for(var b=a.length,c=Array(b),d=0;d<b;d++)c[d]=a.L(d);a=c}return String.fromCharCode.apply(this,a)};function M(a,b){var c=true;b==null?(b=0,c=false):b<0&&h(nb(b));var d;d=ob(pb([K(a,0)]));d=D(Array(b),Array.h(hb(d).i));d.X=c;return d};Array.h=function(a){return I(F("Array"),Array.C,a)};Array.C=function(a,b){Array.v(a,b);a.q=[]};Array.v=function(a,b){var c=Array.h(b);a.b[c.c]=c;qb(a,[K(a.i,0)])};e=Array.prototype;e.La=1;e.L=function(a){if(0<=a&&a<this.length)return this.sa(a);h(aa(a))};e.T=function(a,b){(a<0||this.length<=a)&&h(aa(a));this[a]=b};
e.za=function(){var a;if(this.X){a=rb([K(L(this,F("Array")),0)]);var b=new N;b.f=a;Object.g.call(b);b.M=this;b.R=0;b.P=this.length}else a=sb([K(L(this,F("Array")),0)]),b=new O,b.f=a,Object.g.call(b),b.M=this,b.R=0;Object.d.call(b);return a=b};e.oa=function(a,b){(0!=b.a||0+a!=0)&&n();return Array.prototype.za.call(this)};e.sa=function(a){return this[a]};e.da=function(){return this.length};e.s=function(a){for(var b=this.oa(0,q);b.aa(0,q);){var c=b.pa(0,q);a(1,q,c)}};
e.wa=function(a,b,c){(0!=b.a||0+a!=1)&&n();return Array.prototype.s.call(this,c)};e.J=function(){return this.length===0};e.n=function(a){this.X?h(t(tb("Cannot add to a non-extendable array"))):this.push(a)};e.S=function(a){this.n(a)};e.Z=function(){this.X?h(t(tb("Cannot clear a non-extendable array"))):this.X?h(t(tb("Cannot change the length of a non-extendable array"))):this.length=0};Array.d=function(){Object.d.call(this)};Array.g=function(){Object.g.call(this)};
Array.Ab=function(a){var b=[];b.f=a;Array.g.call(b);Array.d.call(b);return b};function N(a,b,c){this.M=a;this.R=b;this.P=c}function rb(a){return I(F("FixedSizeArrayIterator$Dart"),ub,a)}function ub(a,b){var c=rb(b);a.b[c.c]=c;vb(a,[K(a.i,0)]);a.q=[]}ga(N,O);N.prototype.I=function(){return this.P>this.R};N.prototype.aa=function(a,b){(0!=b.a||0+a!=0)&&n();return N.prototype.I.call(this)};function O(a,b){this.M=a;this.R=b}function sb(a){return I(F("VariableSizeArrayIterator$Dart"),wb,a)}function wb(a,b){vb(a,b);a.q=[]}function vb(a,b){var c=sb(b);a.b[c.c]=c;xb(a,[K(a.i,0)])}O.prototype.I=function(){return this.M.length>this.R};O.prototype.aa=function(a,b){(0!=b.a||0+a!=0)&&n();return O.prototype.I.call(this)};O.prototype.Ba=function(){this.I()||h(t(yb()));return this.M[f(this.M,this.R++)]};O.prototype.pa=function(a,b){(0!=b.a||0+a!=0)&&n();return O.prototype.Ba.call(this)};Boolean.h=function(){return I(F("Boolean"),Boolean.C)};Boolean.C=function(a){Boolean.v(a)};Boolean.v=function(a){var b=Boolean.h();a.b[b.c]=b;b=I(F("bool$Dart"));a.b[b.c]=b};Boolean.prototype.U=function(a){return typeof a=="boolean"?this==a:a instanceof Boolean?this==Boolean(a):false};Boolean.prototype.j=function(){return this==true?"true":"false"};Boolean.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Boolean.prototype.j.call(this)};Boolean.d=function(){Object.d.call(this)};Boolean.g=function(){Object.g.call(this)};
Boolean.sb=function(){var a=new Boolean;a.f=Boolean.h();Boolean.g.call(a);Boolean.d.call(a);return a};function qa(a){return r(a)};function ab(){}function zb(a){var b=I(F("SendPortImpl$Dart"),zb);a.b[b.c]=b;Ab(a)}e=ab.prototype;e.Na=1;function P(a,b,c){var d=new ab;d.f=I(F("SendPortImpl$Dart"),zb);Object.g.call(d);d.H=a;d.F=b;d.G=c;Object.d.call(d);return d}function Oa(a,b,c){(0!=c.a||0+b!=1)&&n();Ia.call(this,a.message,a.ga)}e.U=function(a){return!!(a!=null&&a.Na)&&l(this.H,a.H)&&l(this.F,a.F)&&l(this.G,a.G)};e.ba=function(){return this.H<<16^this.F<<8^this.G};e.na=function(a,b){(0!=b.a||0+a!=0)&&n();return ab.prototype.ba.call(this)};
e.t=function(){return F("SendPortImpl$Dart")+(":"+r(this.G))+(":"+r(this.F))+(":"+r(this.H))};var Bb;function Ha(a,b){this.la=a;this.V=b}function Cb(){return I(F("ReceivePortImpl$Dart"),Db)}function Db(a){var b=Cb();a.b[b.c]=b;b=I(F("ReceivePort$Dart"));a.b[b.c]=b}Ha.prototype.bb=1;function Ga(){Bb=u.Qa;var a=ha(Bb,1);u.Qa=a;a=new Ha(Bb,void 0);Object.d.call(this);a.f=Cb();Object.d.call(a);var b=a.la,c=u;c.Da.a===0&&Ba(ta,c.id,c);Ba(c.Da,b,a);return a}Ha.prototype.Fa=function(){return P(y,u.id,this.la)};function cb(a){var b=new Eb;b.f=I(F("Copier$Dart"),Fb);Object.g.call(b);Object.d.call(b);return Gb(b,a)}function bb(a){var b=new Hb;b.f=I(F("Serializer$Dart"),Ib);Object.g.call(b);b.ma=0;Object.d.call(b);return Gb(b,a)}function xa(a){var b=Jb();0!=q.a&&n();return Kb.prototype.gb.call(b,a)};function Lb(a){this.B=a}function Mb(a){var b=I(F("MessageTraverser$Dart"));a.b[b.c]=b}function Nb(a){return a==null||String.D(a)||!!(a!=null&&a.Oa)||Boolean.D(a)}e=Lb.prototype;e.ob=function(a){if(Nb(a))return this.qa(a);this.B=M(null,void 0);var b=void 0;try{b=Q(this,a)}finally{for(var a=this.B.length,c=0;c<a;c++)this.B[f(this.B,c)].__MessageTraverser__attached_info__=void 0;this.B=void 0}return b};function Gb(a,b){0!=q.a&&n();return Lb.prototype.ob.call(a,b)}
function Ob(a,b,c){a.B.n(b);b.__MessageTraverser__attached_info__=c}function Q(a,b){if(Nb(b))return a.qa(b);if(b!=null&&b.La)return a.Ha(b);if(b!=null&&b.Ma)return a.Ia(b);if(b!=null&&b.Na)return a.ha(b);if(b!=null&&b.bb)return a.Ja(b);if(b!=null&&b.rb)return a.Ka(b);h("Message serialization: Illegal value "+R(b)+" passed")}e.qa=function(){};e.Ha=function(){};e.Ia=function(){};e.ha=function(){};e.Ja=function(){};e.Ka=function(){};function Pb(a){return a.__MessageTraverser__attached_info__};function Eb(a){this.B=a}function Fb(a){var b=I(F("Copier$Dart"),Fb);a.b[b.c]=b;Mb(a)}ga(Eb,Lb);e=Eb.prototype;e.qa=function(a){return a};e.Ha=function(a){var b=Pb(a);if(b!=null)return b;var c=a.length,b=M(null,c);Ob(this,a,b);for(var d=0;d<c;d++)b[f(b,d)]=Q(this,a[f(a,d)]);return b};function Qb(a,b,c,d,g){(0!=c.a||0+b!=2)&&n();a.copy.T(Q(this,d),Q(this,g))}e.Ia=function(a){var b;b={};b.copy=Pb(a);if(b.copy!=null)return b.copy;b.copy=Rb();Ob(this,a,b.copy);a.wa(1,q,da(Qb,this,b));return b.copy};
e.ha=function(a){return P(a.H,a.F,a.G)};e.Ja=function(a){return P(y,u.id,a.la)};e.Ka=function(a){return P(y,u.id,a.la)};function Hb(a,b){this.B=a;this.ma=b}function Ib(a){var b=I(F("Serializer$Dart"),Ib);a.b[b.c]=b;Mb(a)}ga(Hb,Lb);e=Hb.prototype;e.qa=function(a){return a};e.Ha=function(a){var b=Pb(a);if(b!=null)return S(D(["ref",b],Array.h()));b=this.ma++;Ob(this,a,b);a=Sb(this,a);return S(D(["list",b,a],Array.h()))};e.Ia=function(a){var b=Pb(a);if(b!=null)return S(D(["ref",b],Array.h()));b=this.ma++;Ob(this,a,b);var c=Sb(this,pa(a));0!=q.a&&n();a=T.prototype.jb.call(a);a=Sb(this,a);return S(D(["map",b,c,a],Array.h()))};
e.ha=function(a){return S(D(["sendport",a.H,a.F,a.G],Array.h()))};e.Ja=function(a){return this.ha(a.Fa())};e.Ka=function(a){return this.ha(a.Fa())};function Sb(a,b){for(var c=b.length,d=Array(c),g=0;g<c;g++){var m=Q(a,b[f(b,g)]);d[g]=m}return d}function S(a){if(a instanceof Array)a.f=null;else{for(var b=a.length,c=Array(b),d=0;d<b;d++)c[d]=a.L(d);a=c}return a};function Kb(a){this.ka=a}function Jb(){var a=new Kb(void 0);Object.d.call(this);a.f=I(F("Deserializer$Dart"));Object.d.call(a);return a}function Tb(a){return a==null||String.D(a)||!!(a!=null&&a.Oa)||Boolean.D(a)}Kb.prototype.gb=function(a){if(Tb(a))return a;this.ka=Rb();return Ub(this,a)};
function Ub(a,b){if(Tb(b))return b;k(b instanceof Array);switch(b[0]){case "ref":var c=a.ka.L(b[1]);k(c!=null);return c;case "list":var d=b[1],c=b[2];k(c instanceof Array);k(!!(c!=null&&c.La));a.ka.T(d,c);for(var d=c.length,g=0;g<d;g++)c[f(c,g)]=Ub(a,c[f(c,g)]);return c;case "map":c=Rb();a.ka.T(b[1],c);d=b[2];g=b[3];k(d instanceof Array);k(g instanceof Array);var m=d.length;k(m===g.length);for(var p=0;p<m;p++){var C=Ub(a,d[p]),s=Ub(a,g[p]);c.T(C,s)}return c;case "sendport":return P(b[1],b[2],b[3]);
default:h("Unexpected serialized object")}};Number.h=function(){return I(F("Number"),Number.C)};Number.C=function(a){Number.v(a)};Number.v=function(a){var b=Number.h();a.b[b.c]=b;Vb(a);Wb(a)};e=Number.prototype;e.Oa=1;e.Pa=function(a){return this+a};e.U=function(a){return typeof a=="number"?this==a:a instanceof Number?this==Number(a):false};e.j=function(){return this.toString()};e.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Number.prototype.j.call(this)};e.ba=function(){return this&268435455};e.na=function(a,b){(0!=b.a||0+a!=0)&&n();return Number.prototype.ba.call(this)};
Number.d=function(){Object.d.call(this)};Number.g=function(){Object.g.call(this)};Number.zb=function(){var a=new Number;a.f=Number.h();Number.g.call(a);Number.d.call(a);return a};String.h=function(){return I(F("String"),String.C)};String.C=function(a){String.v(a)};String.v=function(a){var b=String.h();a.b[b.c]=b;Xb(a)};String.Bb=function(a){return String.Xa(a)};e=String.prototype;e.L=function(a){if(0<=a&&a<this.length)return this.sa(a);h(aa(a))};e.da=function(){return this.length};e.U=function(a){return typeof a=="string"?this==a:a instanceof String?this==String(a):false};e.J=function(){return this.length===0};e.Pa=function(a){return this.concat(a.o(0,q))};
e.ba=function(){if(this.r===void 0){for(var a=0;a<this.length;a++)this.r+=this.charCodeAt(a),this.r+=this.r<<10,this.r^=this.r>>6;this.r+=this.r<<3;this.r^=this.r>>11;this.r+=this.r<<15;this.r&=536870911}return this.r};e.na=function(a,b){(0!=b.a||0+a!=0)&&n();return String.prototype.ba.call(this)};e.j=function(){return String(this)};e.o=function(a,b){(0!=b.a||0+a!=0)&&n();return String.prototype.j.call(this)};String.Xa=function(a){return mb(a)};String.eb=function(a,b,c){(0!=b.a||0+a!=1)&&n();return String.Xa(c)};
String.Cb=function(){return String.eb};String.prototype.sa=function(a){return this[a]};function R(a){return a==null?"null":a.o(0,q)};function Yb(){}function Zb(){return I(F("StringBufferImpl$Dart"),$b)}function $b(a){var b=Zb();a.b[b.c]=b;b=I(F("StringBuffer$Dart"));a.b[b.c]=b}function oa(){var a=new Yb;a.f=Zb();Object.g.call(a);Object.d.call(a);a.Z();a.n("");return a}e=Yb.prototype;e.da=function(){return this.P};e.J=function(){return this.P===0};e.n=function(a){a=a.o(0,q);if(a==null||a.J())return this;this.z.n(a);this.P+=a.da();return this};
e.Z=function(){var a=[I(F("String$Dart"),ac)],b=void 0,c=true;b==null?(b=0,c=false):b<0&&h(nb(b));a=ob(pb([K(a,0)]));b=D(Array(b),Array.h(hb(a).i));b.X=c;this.z=b;this.P=0;return this};e.j=function(){if(this.z.length===0)return"";if(this.z.length===1)return this.z[f(this.z,0)];var a;a=this.z;for(var b="",c=0;c<a.length;c++){c>0&&(b=b.concat(""));var d=a[f(a,c)],b=b.concat(d)}a=b;this.z.Z();this.z.n(a);return a};e.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Yb.prototype.j.call(this)};function bc(){}function pb(a){return I(F("TypeToken$Dart"),null,a)}function ob(a){var b=new bc;b.f=a;Object.g.call(b);Object.d.call(b);return b}bc.prototype.t=function(){return F("TypeToken$Dart")};function cc(a,b){qb(a,b);a.q=[]}function qb(a,b){var c=I(F("Array$Dart"),cc,b);a.b[c.c]=c;dc(a,[K(a.i,0)])};function T(){}function ec(a){return I(F("HashMapImplementation$Dart"),fc,a)}function fc(a,b){var c=ec(b);a.b[c.c]=c;gc(a,[K(a.i,0),K(a.i,1)]);a.q=[]}e=T.prototype;e.Ma=1;function Rb(){var a=ec(),b=new T;b.f=a;Object.g.call(b);Object.d.call(b);if(u.K==null)a=Object.cb(),u.K=a;b.A=0;b.Y=0;a=ia(24);b.Va=a;b.e=M(null,8);b.k=M([K(L(b,F("HashMapImplementation$Dart")),1)],8);return b}
function hc(a,b){var c;c=b.na(0,q)&a.e.length-1;for(var d=1,g=-1;;){var m=a.e[f(a.e,c)];if(m==null)return g<0?c:g;else if(l(m,b))return c;else g<0&&u.K===m&&(g=c);m=d++;c=c+m&a.e.length-1}}function ic(a,b){var c;c=b.na(0,q)&a.e.length-1;for(var d=1;;){var g=a.e[f(a.e,c)];if(g==null)return-1;if(l(g,b))return c;g=d++;c=c+g&a.e.length-1}}
function jc(a,b){k((b&b-1)===0);var c=a.e.length;a.Va=ia(b*3);var d=a.e,g=a.k;a.e=M(null,b);a.k=M([K(L(a,F("HashMapImplementation$Dart")),1)],b);for(var m=0;m<c;m++){var p=d[f(d,m)];if(!(p==null||p===u.K)){var C=g[f(g,m)],s=hc(a,p);a.e[f(a.e,s)]=p;a.k[f(a.k,s)]=C}}a.Y=0}e.Z=function(){this.Y=this.A=0;for(var a=this.e.length,b=0;b<a;b++)this.e[f(this.e,b)]=void 0,this.k[f(this.k,b)]=void 0};
e.T=function(a,b){var c=this.A+1;c>=this.Va?jc(this,this.e.length*2):this.Y>this.e.length-c-this.Y&&jc(this,this.e.length);c=hc(this,a);(this.e[f(this.e,c)]==null||this.e[f(this.e,c)]===u.K)&&this.A++;this.e[f(this.e,c)]=a;this.k[f(this.k,c)]=b};e.L=function(a){a=ic(this,a);return a<0?void 0:this.k[f(this.k,a)]};e.fa=function(a){a=ic(this,a);if(a>=0){this.A--;var b=this.k[f(this.k,a)];this.k[f(this.k,a)]=void 0;this.e[f(this.e,a)]=u.K;this.Y++;return b}};
e.Ea=function(a,b,c){(0!=b.a||0+a!=1)&&n();return T.prototype.fa.call(this,c)};e.J=function(){return this.A===0};e.da=function(){return this.A};e.s=function(a){for(var b=this.e.length,c=0;c<b;c++)this.e[f(this.e,c)]!=null&&this.e[f(this.e,c)]!==u.K&&a(2,q,this.e[f(this.e,c)],this.k[f(this.k,c)])};e.wa=function(a,b,c){(0!=b.a||0+a!=1)&&n();return T.prototype.s.call(this,c)};function kc(a,b,c,d){(0!=c.a||0+b!=2)&&n();a.list[f(a.list,a.xa++)]=d}
e.ib=function(){var a;a={};a.list=M([K(L(this,F("HashMapImplementation$Dart")),0)],this.A);a.xa=0;this.s(da(kc,void 0,a));return a.list};function pa(a){0!=q.a&&n();return T.prototype.ib.call(a)}function lc(a,b,c,d,g){(0!=c.a||0+b!=2)&&n();a.list[f(a.list,a.xa++)]=g}e.jb=function(){var a;a={};a.list=M([K(L(this,F("HashMapImplementation$Dart")),1)],this.A);a.xa=0;this.s(da(lc,void 0,a));return a.list};function mc(){}function nc(a,b){var c=I(F("PromiseImpl$Dart"),nc,b);a.b[c.c]=c;c=[K(a.i,0)];c=I(F("Promise$Dart"),null,c);a.b[c.c]=c;a.q=[]}function Ma(){var a=I(F("PromiseImpl$Dart"),nc,void 0),b=new mc;b.f=a;Object.g.call(b);b.p=0;b.ta=void 0;b.ra=void 0;b.Q=void 0;b.O=void 0;b.ja=void 0;Object.d.call(b);return b}function U(a){return a.p!==0&&a.p!==1}function oc(a,b,c,d){(0!=c.a||0+b!=1)&&n();d(1,q,a.Aa)}
function pc(a,b){var c={Aa:b};a.p===4?(a.ta=c.Aa,a.p=5):(U(a)&&h("Attempted to complete an already completed promise."),a.ta=c.Aa,a.p=2,a.Q!=null&&a.Q.s(j(oc,void 0,c)),qc(a))}function qc(a){a.Q=void 0;a.O=void 0;a.ja=void 0}function rc(a,b,c,d){(0!=c.a||0+b!=1)&&n();d(1,q,a.va)}function sc(a,b){var c={va:b};a.p===4?(a.ra=c.va,a.p=6):(U(a)&&h("Can't fail an already completed promise."),a.ra=c.va,a.p=3,a.O!=null&&a.O.s(j(rc,void 0,c)),qc(a))}
function fa(a,b,c,d,g){(0!=d.a||0+c!=1)&&n();pc(b.Ca,a.fb(1,q,g))}function tc(a,b,c,d){(0!=c.a||0+b!=1)&&n();sc(a.Ca,d)}function uc(a,b,c){(0!=c.a||0+b!=0)&&n();sc(a.Ca,"Source promise was cancelled")}
function La(a,b){var c={fb:b},d;d={};d.Ca=Ma();c=ea(c,d);if(a.p===2)c(1,q,a.ta);else if(!U(a)){if(a.Q==null)a.Q=Ja();a.Q.S(c)}c=j(tc,void 0,d);if(a.p===3)c(1,q,a.ra);else if(!U(a)){if(a.O==null)a.O=Ja();a.O.S(c)}d=ca(uc,d);if(a.p===4||a.p===5||a.p===6)d(0,q);else if(!U(a)){if(a.ja==null)a.ja=Ja();a.ja.S(d)}};function Ka(a,b,c){(0!=c.a||0+b!=1)&&n();k(a.Ga>0);a.Ga--}function Na(a,b,c){(0!=c.a||0+b!=0)&&n();a.Ga>0?a=false:(pc(a.result,void 0),a=true);return a}function ya(){if(u.w!=null)for(;!u.w.J()&&u.w.m.l.ua()(0,q);)u.w.m.l.Ea(0,q)};function V(a,b,c){this.u=a;this.l=b;this.N=c}function vc(a){return I(F("DoubleLinkedQueueEntry$Dart"),null,a)}V.prototype.Ua=function(a,b){this.l=b;this.u=a;a.l=this;b.u=this};V.prototype.fa=function(){this.u.l=this.l;this.l.u=this.u;this.u=this.l=void 0;return this.N};V.prototype.Ea=function(a,b){(0!=b.a||0+a!=0)&&n();return V.prototype.fa.call(this)};V.prototype.ua=function(){return this.N};function W(a,b,c){this.u=a;this.l=b;this.N=c}function wc(a){return I(F("_DoubleLinkedQueueEntrySentinel$Dart"),xc,a)}function xc(a,b){var c=wc(b);a.b[c.c]=c;c=[K(a.i,0)];c=vc(c);a.b[c.c]=c;a.q=[]}ga(W,V);W.prototype.fa=function(){h(t(yc()))};W.prototype.Ea=function(a,b){(0!=b.a||0+a!=0)&&n();return W.prototype.fa.call(this)};W.prototype.ua=function(){h(t(yc()))};function zc(){}function Ac(a){return I(F("DoubleLinkedQueue$Dart"),Bc,a)}function Bc(a,b){var c=Ac(b);a.b[c.c]=c;Cc(a,[K(a.i,0)]);a.q=[]}function Ja(){var a=Ac([I(F("Function$Dart"))]),b=new zc;b.f=a;Object.g.call(b);Object.d.call(b);var a=wc([K(L(b,F("DoubleLinkedQueue$Dart")),0)]),c=new W;c.f=a;Object.g.call(c);Object.d.call(c);c.N=void 0;c.Ua(c,c);b.m=c;return b}e=zc.prototype;
e.S=function(a){var b=this.m,c=vc([K(L(b,F("DoubleLinkedQueueEntry$Dart")),0)]),d=new V;d.f=c;Object.g.call(d);Object.d.call(d);d.N=a;a=b.u;0!=q.a&&n();V.prototype.Ua.call(d,a,b)};e.n=function(a){this.S(a)};function Dc(a,b,c){(0!=c.a||0+b!=1)&&n();a.Za++}e.da=function(){var a;a={Za:0};this.s(j(Dc,void 0,a));return a.Za};e.J=function(){return this.m.l===this.m};e.Z=function(){this.m.l=this.m;this.m.u=this.m};e.s=function(a){for(var b=this.m.l;b!==this.m;)a(1,q,b.N),b=b.l};
e.wa=function(a,b,c){(0!=b.a||0+a!=1)&&n();return zc.prototype.s.call(this,c)};e.za=function(){return Ec(Fc([K(L(this,F("DoubleLinkedQueue$Dart")),0)]),this.m)};e.oa=function(a,b){(0!=b.a||0+a!=0)&&n();return zc.prototype.za.call(this)};function X(a,b){this.m=a;this.W=b}function Fc(a){return I(F("_DoubleLinkedQueueIterator$Dart"),Gc,a)}function Gc(a,b){var c=Fc(b);a.b[c.c]=c;xb(a,[K(a.i,0)]);a.q=[]}function Ec(a,b){var c=new X(b,void 0);Object.d.call(this);c.f=a;Object.d.call(c);c.W=c.m;return c}X.prototype.I=function(){return this.W.l!==this.m};X.prototype.aa=function(a,b){(0!=b.a||0+a!=0)&&n();return X.prototype.I.call(this)};X.prototype.Ba=function(){this.I()||h(t(yb()));this.W=this.W.l;return this.W.ua()};
X.prototype.pa=function(a,b){(0!=b.a||0+a!=0)&&n();return X.prototype.Ba.call(this)};Object.h=function(){return I(F("Object"))};Object.v=function(a){var b=Object.h();a.b[b.c]=b};Object.d=function(){};Object.g=function(){};Object.cb=function(){var a={};a.f=Object.h();Object.d.call(a);return a};Object.prototype.U=function(a){return this===a};Object.prototype.j=function(){return"Object"};Object.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Object.prototype.j.call(this)};Object.prototype.t=function(){return F("Object")+(":"+r(this.Hb))};function Ra(a){0!=q.a&&n();a=a==null?"null":a.o(0,q);fb(a)};function Hc(a,b){Ic(a,b);a.q=[]}function Ic(a,b){var c=I(F("Collection$Dart"),Hc,b);a.b[c.c]=c;c=[K(a.i,0)];c=I(F("Iterable$Dart"),null,c);a.b[c.c]=c};function Jc(a){Wb(a)}function Wb(a){var b=I(F("double$Dart"),Jc);a.b[b.c]=b;Kc(a)};function Y(a){var b=I(F("Exception$Dart"));a.b[b.c]=b};function Z(){}function Lc(){return I(F("IndexOutOfRangeException$Dart"),Mc)}function Mc(a){var b=Lc();a.b[b.c]=b;Y(a)}function aa(a){var b=new Z;b.f=Lc();Object.g.call(b);b.Ta=a;Object.d.call(b);return b}Z.prototype.j=function(){return"IndexOutOfRangeException: "+R(this.Ta)+""};Z.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Z.prototype.j.call(this)};Z.prototype.t=function(){return F("IndexOutOfRangeException$Dart")+(":"+r(this.Ta))};function o(){}function ja(){return I(F("NoSuchMethodException$Dart"),Nc)}function Nc(a){var b=ja();a.b[b.c]=b;Y(a)}o.prototype.j=function(){for(var a=oa(),b=0;b<this.ia.length;b++)b>0&&a.n(", "),a.n(this.ia[f(this.ia,b)]);a.n("]");return ha("NoSuchMethodException - receiver: '"+R(this.Ya)+"' ","function name: '"+R(this.Sa)+"' arguments: ["+R(a)+"]")};o.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return o.prototype.j.call(this)};
o.prototype.t=function(){return F("NoSuchMethodException$Dart")+(":"+r(this.Ya))+(":"+r(this.Sa))+(":"+r(this.ia))};function $(){}function Oc(){return I(F("IllegalArgumentException$Dart"),Pc)}function Pc(a){var b=Oc();a.b[b.c]=b;Y(a)}function nb(a){var b=new $;b.f=Oc();Object.g.call(b);b.Ra=a;Object.d.call(b);return b}$.prototype.j=function(){return"Illegal argument(s): "+R(this.Ra)+""};$.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return $.prototype.j.call(this)};$.prototype.t=function(){return F("IllegalArgumentException$Dart")+(":"+r(this.Ra))};function Qc(){}function Rc(){return I(F("NoMoreElementsException$Dart"),Sc)}function Sc(a){var b=Rc();a.b[b.c]=b;Y(a)}function yb(){var a=new Qc;a.f=Rc();Object.g.call(a);Object.d.call(a);return a}Qc.prototype.j=function(){return"NoMoreElementsException"};Qc.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Qc.prototype.j.call(this)};Qc.prototype.t=function(){return F("NoMoreElementsException$Dart")};function Tc(){}function Uc(){return I(F("EmptyQueueException$Dart"),Vc)}function Vc(a){var b=Uc();a.b[b.c]=b;Y(a)}function yc(){var a=new Tc;a.f=Uc();Object.g.call(a);Object.d.call(a);return a}Tc.prototype.j=function(){return"EmptyQueueException"};Tc.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Tc.prototype.j.call(this)};Tc.prototype.t=function(){return F("EmptyQueueException$Dart")};function Wc(){}function Xc(){return I(F("UnsupportedOperationException$Dart"),Yc)}function Yc(a){var b=Xc();a.b[b.c]=b;Y(a)}function tb(a){var b=new Wc;b.f=Xc();Object.g.call(b);b.Wa=a;Object.d.call(b);return b}Wc.prototype.j=function(){return"UnsupportedOperationException: "+R(this.Wa)+""};Wc.prototype.o=function(a,b){(0!=b.a||0+a!=0)&&n();return Wc.prototype.j.call(this)};Wc.prototype.t=function(){return F("UnsupportedOperationException$Dart")+(":"+r(this.Wa))};function Zc(a){var b=I(F("Hashable$Dart"));a.b[b.c]=b};function $c(a){Vb(a)}function Vb(a){var b=I(F("int$Dart"),$c);a.b[b.c]=b;Kc(a)};function ad(a){Ab(a)}function Ab(a){var b=I(F("SendPort$Dart"),ad);a.b[b.c]=b;Zc(a)};function xb(a,b){var c=I(F("Iterator$Dart"),null,b);a.b[c.c]=c};function bd(a,b){dc(a,b);a.q=[]}function dc(a,b){var c=I(F("List$Dart"),bd,b);a.b[c.c]=c;Ic(a,[K(a.i,0)])};function cd(a,b){gc(a,b);a.q=[]}function gc(a,b){var c=I(F("HashMap$Dart"),cd,b);a.b[c.c]=c;c=[K(a.i,0),K(a.i,1)];c=I(F("Map$Dart"),null,c);a.b[c.c]=c};function dd(a){Kc(a)}function Kc(a){var b=I(F("num$Dart"),dd);a.b[b.c]=b;b=I(F("Comparable$Dart"));a.b[b.c]=b;Zc(a)};function ed(a,b){Cc(a,b);a.q=[]}function Cc(a,b){var c=I(F("Queue$Dart"),ed,b);a.b[c.c]=c;Ic(a,[K(a.i,0)])};function ac(a){Xb(a)}function Xb(a){var b=I(F("String$Dart"),ac);a.b[b.c]=b;b=I(F("Comparable$Dart"));a.b[b.c]=b;Zc(a);b=I(F("Pattern$Dart"));a.b[b.c]=b};v.push(function(){this.V=i;u.Qa=1});v.push(function(){this.ma=0});v.push(function(){u.Fb=i;u.Eb=i;u.Gb=i});v.push(function(){u.vb=i;u.ub=i;u.tb=i;u.yb=i;u.xb=i;u.wb=i});(function(a,b){if(!x){var c=new Fa;wa(c,function(){a(b)});Pa();u=c}})(function(){Ra("Hello, Dart!")},this.arguments?this.arguments.slice?[].concat(this.arguments.slice()):this.arguments:[]);

I wish I was joking.

See that code live here.

JavaScript in <head> or just before </body>?

18 votes

I am about to embark on a new web project and I plan to put my JS-scripts in the head and before end-body using the following scheme:

  1. Scripts that are essential for the UX of the page goes in the head. As I've picked up perusing the web - scripts in the head is loaded before the page loads, so it would make sense to put scripts that are essential to the user experience there.

  2. Scripts that are non-essential to the design and UX (Google Analytics scripts etc.) of the page goes before the </body>.

Is this a sensible approach?

Another approach would be to put all the scripts in the <head> and add defer attributes to the non-essential scripts - however I've read that older versions of FF doesn't pick up the defer attribute.

I think a lot of developers run javascript just before the </body> so that it is ran after all the elements have been rendered.

However, if you organise your code correctly, the position on the page doesn't matter.

For example, when using jQuery, you can ensure the code isn't ran until the page and its elements are fully rendered by doing the following:

$(document).ready(function(){
   //Code here
});

Then the script reference can be put in the head tag.

Why presize a JavaScript Array?

18 votes

Firebug represents (new Array(N)) as an array with N undefineds in it. I recently ran across a scenario that demonstrated that a sized array with all undefined values in it is different from a newly constructed, sized array. I'd like to understand the difference.

Suppose you want to generate a list of random integers between 0 and 1000.

function kilorange() {
    return Math.floor(Math.random() * (1001));
}

no_random_numbers = (new Array(6)).map(kilorange);
my_random_numbers = [undefined, undefined, undefined,
                     undefined, undefined, undefined].map(kilorange);

I would have expected no_random_numbers and my_random_numbers to be equivalent, but they're not. no_random_numbers is another array of undefineds, whereas my_random_numbers is an array with six random integers in it. Furthermore, after throwing a console.count statement into kilorange, I learned that my function never gets called for the array created with the Array constructor.

What is the difference, and why does map (and presumably other iterable methods) not treat the above arrays the same?

The ES standard (15.4.4.19) defines the algorithm for map, and it's quite clear from step 8b that since your array doesn't actually have any of those elements, it will return an "empty" array with length 6.

As others have mentioned, it has to do with array objects in js being (unlike their rigid C counterparts) very dynamic, and potentially sparse (see 15.4 for the sparsity test algorithm).

How are JavaScript host objects implemented?

18 votes

I was thinking about this today and I realized I don't have a clear picture here.

Here are some statements I think to be true (please correct me if I'm wrong):

  • the DOM is a collection of interfaces specified by W3C.
  • when parsing HTML source code, the browser creates a DOM tree which has nodes that implement DOM interfaces.
  • the ECMAScript spec has no reference of browser host objects (DOM, BOM, HTML5 APIs etc.).
  • how the DOM is actually implemented depends on browser internals and is probably different among most of them.
  • modern JS interpreters use JIT to improve the code performance and translate it to bytecode

I am curious about what happens behind the scenes when I call document.getElementById('foo'). Does the call get delegated to browser native code by the interpreter or does the browser have JS implementations of all host objects? Do you know about any optimizations they do in regard to this?

I read this overview of browser internals but it didn't mention anything about this. I will look through the Chrome and FF source when I have time, but I thought about asking here first. :)

All of your bullet points are correct, except:

modern JS interpreters use JIT to improve the code performance and translate it to bytecode

should be "...and translate it to native code". SpiderMonkey (the JS engine in Firefox) worked as a bytecode interpreter for a long time before the current JS speed arms race.

On Mozilla's JS-to-DOM bridge:

The host objects are typically implemented in C++, though there is an experiment underway to implement DOM in JS. So when a web page calls document.getElementById('foo'), the actual work of retrieving the element by its ID is done in a C++ method, as hsivonen noted.

The specific way the underlying C++ implementation gets called changed over time (note that I'm not involved in the development, so might be wrong about some details):

  • At the lowest level every JS engine provides APIs to define host objects. For example, the browser can call JS_DefineFunctions (as demonstrated in the SpiderMonkey User Guide) to let the engine know that whenever script calls a function with the specified name, a provided C callback should be called. Same for other aspects of the host objects (e.g. enumeration, property getters/setters, etc.)
  • For the core ECMAScript functionality and in some tricky DOM cases the JS engine/the browser uses these APIs directly to define host objects and their behaviors, but it requires a lot of common boilerplate code for e.g. checking parameter types, converting them to the appropriate C++ types, error handling etc.
  • For reasons I won't go into, let's say historically, Mozilla made heavy use of XPCOM for many of its objects, including much of the DOM. One feature of XPCOM is its binding to JS called XPConnect. Among other things, XPConnect can take an interface definition in IDL (such as nsIDOMDocument; or more precisely its compiled representation), expose an object with the specified properties to the script, and later, when a script calls getElementById, perform the necessary parameter checks/conversions and route the call directly to a C++ method (nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn))
  • The way XPConnect worked was quite inefficient: it registered generic functions as callbacks to be executed when a script accesses a host object, and these generic functions figured out what they needed to do in every particular case dynamically. This post about quickstubs walks you through one example.
  • "Quick stubs" mentioned in the previous link is a way to optimize JS->C++ calls time by trading some code size for it: instead of always using generic C++ functions that know how to make any kind of call, the specialized code is automatically generated at the Firefox build time for a pre-defined list of "hot" calls.
  • Later on the JIT (tracemonkey at that time) was taught to generate the code calling C++ methods as part of the native code generated for "hot" paths in JS. I'm not sure how the newer JITs (jaegermonkey) work in this regard.

I'm fuzzy on details of the two last points in particular, so take it with a grain of salt.

The most recent improvements are listed as dependencies of bug 622298, but I don't follow them closely.

Best practice for determining objects type in Javascript

15 votes

If you have an instance of an object in javascript, it seems it that can be difficult to find its actual type, ie

var Point2D = function Point2D(x, y) {
  return {
    X: x,
    Y: y
  }
}

var p = new Point2D(1,1);

typeof p // yields just 'Object' not 'Point2D'

One way around it I found was to make the object its own prototype, and then you can gets its name effectively by calling prototype.constructor.name,

var Point2D = function Point2D(x, y) {
  return {
    X: x,
    Y: y,
    prototype: this
  }
}

new Point2D(1,1).prototype.constructor.name // yields 'Point2D'

Would this be an OK way of doing it (what are the pros/cons?) or is there a better practice I am missing out on?

Thanks.

First we need to fix how you are building your class, since you are tripping in some JS pitfalls and doing some really weird stuff:

function Point2D(x, y){
    //Our constructor/initialization function
    //when run, the 'this object will have
    //Point2D.prototype as its prototype

    this.x = x;
    this.y = y;

    //Don't return a value here! Doing so overrides
    //the default "return this" that we actually want.
}

//You can put things in the Point2D prototype in order to have them
//be shared by all Point2D objects. Normally you want the methods to be shared.
Point2D.prototype.getX = function(){
    return this.x;
};

//Note that there is nothing magical about the "prototype" property.
//It is just where the `new` syntax expects the prototype it will use to be.
//The actual magic property is __proto__ (don't depend on it though
// __proto__ is browser specific and unsafe/evil)

//We now can create points!
var p = new Point2D(17.0, 42.0);
p.getX();

Now we can tackle the part about getting the type names. The better practice you are missing on is not inspecting the type in the first place. From an OO perspective it shouldn't matter how an object is implemented (ts class) but how it behaves and what is its interface (exposed methods and properties). Also, from a Javascript perspective, type names are a second-class hack that don't fit very well with the prototypical OO scheme that is actually used.

Since there are many reasons you could be trying to inspect a type name in the first place, there are many different "best" solutions. Some that I could think of:

  1. If all you case about is "does this object implement a particular point interface" then you can do feature-inspection directly:

    function isPoint(p){
        //check if p has all the methods I expect a point to have:
        //(note that functions are truthy in a boolean context)
        return (p.getX && p.getY);
    }
    
  2. If you use the type names to do dispatching consider using a method instead. Its the natural OO way.

    function speak(obj){
        //fake pseudo-syntax:
        if(obj is of type Cat){ console.log("meow"); }
        if(obj is of type Dog){ console.log("woof"); }
    }
    

    becomes

    Cat.prototype.speak = function(){ console.log("meow"); };
    Dog.prototype.speak = function(){ console.log("woof"); };
    
  3. If you really need some sort of tag, you can explicitely make one, as pointed by some of the other answers already:

    Point2D.prototype.pointType = "2D";
    

    The advantages here are that you can have more than one class have the same "type" if you need to and that you don't have to worry about any of the tricky instanceof or typeof corner cases.

Determine Maximum Possible DIV Height

14 votes

Is there a recommended way to determine the maximum height that a DIV can be set and remain visible per browser? This doesn't appear to be documented anywhere and is highly implementation specific.

For example, see the following test script:

http://jsfiddle.net/NP5Pa/2/

This is a simple test to find the maximum value you can set a DIV style height attribute before the corresponding clientHeight of the element becomes 0. You can confirm this by clicking "Find Max" then incrementing the found height by 1 and clicking "Set Height".

Some examples (Win7/64):

Chrome (14.0) :    134,217,726 px
Safari (5.1)  :    134,217,726 px
IE (9.0)      :     10,737,418 px
FF (7.0.1)    :     17,895,697 px

It's not surprising the WebKit produces the same result, I guess - more surprising that IE and FF are so different.

Is there a better way? And do you get different results in 32bit systems?

--EDIT: Updated the fiddle to stop at 10,000,000,000 (and get there quicker) for Opera. That's a lot of pixels.

This is your code, modified to use binary search (so it's much quicker).

http://jsfiddle.net/thai/zkuGv/4/

It begins at 1 pixel and doubling its size until the it hits the maximum (I use 253, which is the biggest integer that can be stored in JavaScript without losing precision and would make the binary search buggy), or the div collapses to zero pixel.

Suppose we set the div to size h and it disappears, then the maximum size must be between h/2 and h. We binary search from there for a height h that does not make the div disappear when set to height h, but disappears when set to h+1.

Then we can come to a conclusion for Opera: 2147483583 pixels.

Find out whether Chrome console is open

13 votes

I am using this little script to find out whether Firebug is open:

if (window.console && window.console.firebug) {
    //is open
};

And it works well. Now I was searching for half an hour to find a way to detect whether Google Chrome's built-in web developer console is open, but I couldn't find any hint.

This:

if (window.console && window.console.chrome) {
    //is open
};

doesn't work.

EDIT:

So it seems that it is not possible to detect whether the Chrome console is open. But there is a "hack" that works, with some drawbacks:

  • will not work when console is undocked
  • will not work when console is open on page load

So, I am gonna choose Unsigned´s answer for now, but if some1 comes up with a brilliant idea, he is welcome to still answer and I change the selected answer! Thanks!

The docked inspector can be detected (albeit in a slightly 'hacky' way), as per this answer. However, this only works if the inspector is opened after the page finishes loading. If it is opened prior to loading the page, you will not be able to detect it's presence this way.

You may also get false positives when working with certain frame setups.

The bottom line is that there is no documented way to reliably detect the inspector, and no way at all to detect it when undocked. This is most likely due to security concerns. A malicious webpage could conceal its payload when the inspector was open, making it more difficult to debug.

Why *not* "inherit"/extend from Object in JavaScript?

12 votes

It is well-known that declaring objects with JSON notation makes them "inherit" from (or, more precisely, to be built like) the base Object:

myobj={a:1, b:2};

which is nearly equivalent to myobj = Object.create(Object); myobj.a=1; myobj.b=2;

and than:

Object.getPrototypeOf(myobj)

prints the following:

Object
    __defineGetter__: function __defineGetter__() { [native code] }
    __defineSetter__: function __defineSetter__() { [native code] }
    __lookupGetter__: function __lookupGetter__() { [native code] }
    __lookupSetter__: function __lookupSetter__() { [native code] }
    constructor: function Object() { [native code] }
    hasOwnProperty: function hasOwnProperty() { [native code] }
    isPrototypeOf: function isPrototypeOf() { [native code] }
    propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
    toLocaleString: function toLocaleString() { [native code] }
    toString: function toString() { [native code] }
    valueOf: function valueOf() { [native code] }

However, one can call Object.create() while supplying null as an argument:

myobj2 = Object.create(null);

In this case empty prototype will be returned:

Object
    No Properties

And here goes the question: in which cases and why should I care to break the prototype chain to the original Object? Where it can be useful?

Update: as already corrected down below, I mean Object.create(Object.prototype) rather than Object.create(Object) that would return Function object (indeed Object() is a constructor function for Object prototypees).

Instead of this:

myobj = Object.create(Object);

...I think you mean this is the equivalent:

myobj = Object.create(Object.prototype);

...because:

Object.getPrototypeOf( {a:1, b:2} ) === Object.prototype;  // true

As to why to use null early, if your object has no need for any of the properties of Object.prototype, ending the chain early would technically (though marginally) speed up property lookups when a property does not exist on the object in question.

Note that I say "early" because the chain always ends with null.

Object.getPrototypeOf( Object.prototype );  // null


             obj ----------> proto -------> Object.proto -----> null
         +---------+      +---------+      +-------------+     
         |         |      |         |      |             |
         |  foo:1  |      |  bar:1  |      | toString:fn |      null
         |         |      |         |      |             |
         +---------+      +---------+      +-------------+ 
              ^                ^                  ^               X
              |                |                  |               |
obj.foo ------+                |                  |               |
              ^                |                  |               |
obj.bar-------+----------------+                  |               |
              ^                ^                  |               |
obj.toString--+----------------+------------------+               |
              ^                ^                  ^               |
obj.baz-------+----------------+------------------+---------------+

   ^---property lookups

Notice that the baz property does not exist anywhere in the prototype chain.

Because of this, it needs to search each object in sequence until it finally reaches null before it realizes that baz doesn't exist anywhere.

If you eliminate the Object.prototype from the chain, it will get to null a little quicker.

What is the benefit of the Dart language over JavaScript (Node.js)

12 votes

I don't see the point of Dart in terms of the problem they are trying to solve.

I read that it was created due to short comings of JavaScript, however those short comings were not given.

Can someone explain the benefit of learning Dart rather than me learning Node.js?

The technical overview seems to summarize the difference quite well:

  • classes: while JavaScript is object oriented and it does provide classes (at least in its latest incarnations), it is really a prototype-based language and not a class-based language. While that is not inherently worse, it is different from most major OO languages, which makes it harder to learn for most people.

  • (optional) static typing: You can't do static typing (as in: "checked by the compiler") in plain JavaScript. The advantages (and disadvantages) are well-known and have been widely discussed.

  • language support for libraries: "loading that file before this" is a very primitive way of implementing libraries and most modern languages have explicit support for libraries in some way.

That page also mentions tooling, but that's not an inherent difference between languages. Granted, a statically compiled and typed language is easier to write good tools for, but this is not a fundamental difference that can't be solved by programming.

Dom Mutation event in JQuery or vanilla Javscript

11 votes

Are there any DOM mutation events in JQuery or in vanilla Javascript that fire cross browser ?

To clarify, say i have a script on my page which inserts a div into the body. I don't have access to the script and i don't know when the div has been inserted. I was wondering if there's a DOM mutation event that i can add a listener for to know when the div has been inserted. I know i can use some kind of timer to periodically check for the div but i don't really like the overhead that this would impose.

This is certainly a hack, but why not patch the underlying DOM methods used to insert the nodes? There are a couple ways to do this:

A. You know what specific element will be appended to:

var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
     alert('new item added');
     c.__appendChild.apply(c, arguments); 
}

fiddle demo for A

B. You know what type of element will be appended to:

HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
    alert('new item added');
    HTMLDivElement.prototype.__appendChild(this,arguments); 
}

fiddle demo for B

(Note that solution B is not supported by IE < 8 or any other browser which does not support DOM prototypes.)

This same technique could just as easily be used on all the underlying DOM mutation functions such as insertBefore, replaceChild or removeChild.

That's the general idea, these demos could be adapted for pretty much any other use case -- say you want to cast a wide net and catch all additions regardless of type AND make sure it works across all browsers everything but IE < 8? (see example C below)


UPDATE

C. Recursively walk the DOM, swap out the function on every element to trigger a callback, and then apply the same patch to any children being appended.

var DOMwatcher = function(root, callback){
  var __appendChild = document.body.appendChild;

  var patch = function(node){
    if(typeof node.appendChild !== 'undefined' && node.nodeName !== '#text'){
      node.appendChild = function(incomingNode){
        callback(node, incomingNode);
        patch(incomingNode);
        walk(incomingNode);
        __appendChild.call(node, incomingNode);
      };
    }
    walk(node);  
  };

  var walk = function(node){
    var i = node.childNodes.length;
    while(i--){
      patch(node.childNodes[i]);
    }
  };

  patch(root);

};

DOMwatcher(document.body, function(targetElement, newElement){ 
   alert('append detected');    
});

$('#container ul li').first().append('<div><p>hi</p></div>');
$('#container ul li div p').append('<a href="#foo">bar</a>');

fiddle demo for C

UPDATE 2

As Tim Down commented, the above solution also won't work in IE < 8 because appendChild is not a Function and does not support call or apply. I suppose you could always fall back to the clunky but trusty setInterval method if typeof document.body.appendChild !== 'function'.

Will Dart support the use of existing JavaScript libraries?

11 votes

I understand Dart compiles to JavaScript, and I read the Dart Language Spec on Libraries, although I didn't see an answer there. Also a search on their discussion form for the word 'existing' turns up 3 results that are not related.

Does anyone know if Dart will support the use of existing JavaScript libraries such as jQuery or Raphael?

You will not be able to call javascript directly from dart code. The native directive is reserved for the core libraries of dartc (dart:core, dart:dom, dart:html, dart:json, etc), which itself compiles to javascript.

Why is this Javascript much *slower* than its jQuery equivalent?

11 votes

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later):

$('#filter').keyup( function() {
    var jqStart = (new Date).getTime();

    var search = $(this).val().toLowerCase();
    var $list = $('ul.ablist > li');

    $list.each( function() {
        if ( $(this).text().toLowerCase().indexOf(search) === -1 )
            $(this).hide();
        else
            $(this).show();
    } );

    console.log('Time: ' + ((new Date).getTime() - jqStart));
} );

However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent:

document.getElementById('filter').addEventListener( 'keyup', function () {
    var jsStart = (new Date).getTime();

    var search = this.value.toLowerCase();
    var list = document.querySelectorAll('ul.ablist > li');
    for ( var i = 0; i < list.length; i++ )
    {
        if ( list[i].innerText.toLowerCase().indexOf(search) === -1 )
            list[i].style.display = 'none';
        else
            list[i].style.display = 'block';
    }

    console.log('Time: ' + ((new Date).getTime() - jsStart));
}, false );

To my surprise however, the plain Javascript is up to 10 times slower than the jQuery equivalent. The jQuery version takes around 2-3 seconds to filter on each letter, while the Javascript version takes 17+ seconds! I'm using Google Chrome on Ubuntu Linux.

This isn't for anything really important so it doesn't need to be super efficient. But am I doing something really dumb with my Javascript here?

You could try using textContent instead of innerText , I think it should be faster. Also timing the list-generation and loop separately would tell if there is problem in list-generation.

What does $(function() {} ); do?

10 votes

sometimes I make a function and call the function later

for an example...

function example { alert('example'); }

and then call that later

example();

Somehow, some functions are cannot be called and I have to call those function

inside

$(function() { });

I don't get the idea of how this work.

I think it would be much better to know when $(function() {}); or (function() { }); to use

exactly and know the meaning and purpose of it.

$(function() { ... });

is just jQuery short-hand for

$(document).ready(function() { ... });

What it's designed to do (amongst other things) is ensure that your function is called once all the DOM elements of the page are ready to be used.

However, I don't think that's the problem you're having - can you clarify what you mean by 'Somehow, some functions are cannot be called and I have to call those function inside' ? Maybe post some code to show what's not working as expected ?

Edit: Re-reading your question, it could be that your function is running before the page has finished loaded, and therefore won't execute properly; putting it in $(function) would indeed fix that!

jQuery image crossfade with pre-loader

10 votes

I want a simple image crossfade, similar to http://malsup.com/jquery/cycle/, but with a pre-loader. Is there a good jQuery plugin that does both? Also, I'm not looking for a load bar.

This question is close, but not the same => jQuery Crossfade Plugin

It would be great if it was a solution that defaulted to CSS3, but would otherwise fall back to JS to keep the processing native as possible.

Looking for something that..

  • will autoplay
  • without controls
  • will go to the next image based on time setting, ie. 5 seconds, unless the next image isn't loaded in which case it finishes loading the image and then displays it.
  • crossfade transition, not fade to black or white, but cross-fade. from the start it would fadein.
  • no thumbnails or galleries, etc. just the image
  • If images could be CSS background images, that would be best, so users can't drag out the image simply
  • Each panel needs to be clickable so a user could click the image and go to a part of the website.

I think you can still do this with the jQuery cycle plugin; other than image preloading, even the jQuery cycle lite version does everything you want by default out-of-the-box.

And if you look here, you'll see that it's pretty simple to add a little Javascript that will add images (after the first two) as they load. You would need to modify the code a little (instead of stack.push(this), you'd want something like stack.push("<div style="background-image:url("+img.src+")"></div>"), for example) but I think it's totally doable.

Edit: here's a link to a SO question about how to make a div into a clickable link.

Edit 2: I liked Joseph's idea to just move the elements to a hidden DIV, so I updated my code a bit. It now also preserves the links each div points to as well: http://jsfiddle.net/g4Hmh/9/

Edit 3: Last update! http://jsfiddle.net/g4Hmh/12/

Possible to scroll caret into view inside a single HTML text field with JavaScript?

10 votes

Knowing the jQuery Caret plugin, I'm still seeing no way to do the following on a single line text box in HTML (i.e. the input:type=text control) with JavaScript:

  1. Programmatically inserting text into a text box
  2. Setting the caret to the end.
  3. Making the caret visible (i.e. scroll the text box content)

I know how to do 1. and 2., just for 3. I have found no way of doing it.

To illustrate it:

enter image description here

My question is:

Is there any way to reliable put the caret at the end of the text and scroll it into the view?

(I can think of simulating pressing the END key or something like that, but I'm unsure whether this would be the best option).

//hack to get cursor at end:

$(textboxselector).val($(textboxselector).val());

edit: should note focus first:

$(textboxselector).val(newtext);
$(textboxselector).focus();
$(textboxselector).val($(textboxselector).val());

jquery Autocomplete working with older versions of the browsers but not new ones?

9 votes

here is the JSON data for my auto complete

{ "list" : [ {
    "genericIndicatorId" : 100,
    "isActive" : false,
    "maxValue" : null,
    "minValue" : null,
    "modificationDate" : 1283904000000,
    "monotone" : 1,
    "name":"Abbau",
    "old_name" : "abbau_change_delete_imac",
    "position" : 2,
    "systemGraphics" : "000000",
    "unitId" : 1,
    "valueType" : 1,
    "description" : "Abbau",
    "weight" : 1
}]}

and the code which i wrote is

$("#<portlet:namespace />giName").autocomplete({
            source :`enter code here` function( request, response ) {
                $.post(
                    "<%=AJAXgetGIs%>",
                    {
                        "<%=Constants.INDICATOR_NAME%>" : request.term,
                        "<%=Constants.SERVICE_ID%>" : <%=serviceId%>
                    },
                    function( data ) {
                        response( $.map( data.list, function( item ) {
                                //alert(item.name + " || " + item.genericIndicatorId);
                                item.value = item.name;
                            return item;
                        }));
                    },
                    "json"
                );
            },
            minLength : 2

i am using jquery-ui-1.8.14.autocomplete.min.js plugin for auto complete the problem i am getting is it is not showing all the matched results in new browsers. for example if i type "an" in which should matches to the "anzahl" keyword, the fire bug is showing error like "bad control character literal in a string". results are showing for the letters "as,sa....". any help would be appriciated thank you

The error message means you have control characters in your JSON response (something like \n, \t, etc). Newlines and the other control characters are not allowed in JSON strings, according to ECMA262 5ed. You can fix it rather easily by escaping or removing those characters, either from PHP or from Javascript.

Here you can find an example of how you can fix it from PHP, as the problem most likely comes from json_encode (which I assume you're using): http://codepad.org/Qu7uPt0E As you can see, json_encode doesn't escape the \n so you have to do it manually before outputting.

Now for the mistery related to older browsers. If you look at jQuery's parseJSON function you'll notice that it first tries to parse the string with the browser's builtin JSON object and if it doesn't find any, it will just do a (sort of) eval (which will work even with newlines). So it probably works for you on Firefox < 3.5 or IE < 8 which don't have a native JSON object. Also, it probably works with other search terms (like as, etc) simply because they don't include a result which has control characters.

Is it possible to use javascript to detect if a screen reader is running on a users machine?

9 votes

I want to detect whether a screen reader is running on a user's machine to avoid sound clashing with audio tag in html. If so please provide details on how this could be done.

You should probably not try to do anything special even if you could detect that a screenreader is running. Even if you get it right for one group of screenreader users, you may get it wrong for another group. It's best to concentrate on writing good clean HTML5 in the first place.

Note that note all screenreader users use text-to-speech; many use braille output. Additionally, other types of accessibility tools - such as content highlighters and voice input apps - use the same techniques and APIs (eg. DOM, MSAA) that screenreaders do, so any technique that "detects a screenreader" will likely detect these also - so you cannot assume that it means that the user is fully blind and using only speech.

As things currently stand, the audio tag is currently not universally accessible, different browsers have different levels of accessibility support - see http://html5accessibility.com/ and scroll down to audio for more details of current support. I've seen some pages that add HTML5-based controls plus javascript after the audio tag so they can provide their own UI to ensure that keyboard or screenreader users can play/stop the audio as needed. (Eventually, when browsers catch up, this should not be needed.)

As far as general accessibility goes, WCAG 2.0 (Web Content Accessibility Guidelines - http://www.w3.org/TR/WCAG/) recommends that any audio that plays automatically for more than 3 seconds should have an accessible means to pause or stop the audio. (I'd go even further and recommend against using any automatic audio - when using tabbed browsing, it's often impossible to determine which tab the audio is coming from.)

In web browser, what's the difference between onblur and onfocusout?

9 votes

If it is the same, then why there are two of this kind of event.

As you know, the onBlur event fires for an element if that element had the focus, but loses it.

The onFocusOut event fires in this case, but also triggers if any child element loses focus.

For example, you have a div with special formatting because the human is currently editing a field in that area. You'd could use onFocusOut to turn that formatting off when focus leaves that div.

Up until very recently, onFocusOut was only used by IE. If that has changed, it has been very recent. Test in FF, Chrome, etc.

Optimising Database Structure

8 votes

I'm developing a reward system for our VLE which uses three separate technologies - JavaScript for most of the client-side/display processing, PHP to communicate with the database and MySQL for the database itself.

I've attached three screenshots of my "transactions" table. Its structure, a few example records and an overview of its details.

The premise is that members of staff award points to students for good behaviour etc. This can mean that classes of 30 students are given points at a single time. Staff have a limit of 300 points/week and there are around 85 staff currently accessing the system (this may rise).

The way I'm doing it at the moment, every "transaction" has a "Giver_ID" (the member of staff awarding points), a "Recipient_ID" (the student receiving the points), a category and a reason. This way, every time a member of staff issues 30 points, I'm putting 30 rows into the database.

This seemed to work early on, but within three weeks I already have over 12,000 transactions in the database.

At this point it gets a bit more complicated. On the Assign Points page (another screenshot attached), when a teacher clicks into one of their classes or searches for an individual student, I want the students' points to be displayed. The only way I can currently do this on my system is to do a "SELECT * FROM 'transactions'" and put all the information into an array using the following JS:

var Points = { "Recipient_ID" : "0", "Points" : "0" };

function getPoints (data) {
    for (var i = 0; i < data.length; i++) {
        if (Points[data[i].Recipient_ID]) {
            Points[data[i].Recipient_ID] = parseInt(Points[data[i].Recipient_ID]) + parseInt(data[i].Points);
        } else {
            Points[data[i].Recipient_ID] = data[i].Points;
        }
    }
}

When logging in to the system internally, this appears to work quickly enough. When logging in externally however, this process takes around 20 seconds, and thus doesn't display the students' points values until you've clicked/searched a few times.

I'm using the following code in my PHP to access these transactions:

function getTotalPoints() {
    $sql = "SELECT * 
        FROM `transactions`";

    $res = mysql_query($sql);
    $rows = array(); 
    while($r = mysql_fetch_assoc($res)) {
        $rows[] = $r;
    }

    if ($rows) {
        return $rows;
    } else {
        $err = Array("err_id" => 1);
        return $err;
    }
}

So, my question is, how should I actually be approaching this? Full-text indices; maybe a student table with their total points values which gets updated every time a transaction is entered; mass-transactions (i.e. more than one student receiving the same points for the same category) grouped into a single database row? These are all things I've contemplated but I'd love someone with more DB knowledge than myself to provide enlightenment.

Example records Example records

Table structure Table structure

Table overview Table overview

Assign Points interface Assign Points interface

Many thanks in advance.

Your problem is your query:

SELECT * FROM `transactions`

As your data set gets bigger, this will take longer to load and require more memory to store it. Rather determine what data you need specifically. If it's for a particular user:

SELECT SUM(points) FROM `transactions` WHERE Recipient_ID=[x]

Or if you want all the sums for all your students:

SELECT Recipient_ID, SUM(points) AS Total_Points FROM `transactions` GROUP BY Recipient_ID;

To speed up selections on a particular field you can add an index for that field. This will speed up the selections, especially as the table grows.

ALTER TABLE `transactions` ADD INDEX Recipient_ID (Recipient_ID);

Or if you want to display a paginated list of all the entries in transactions:

SELECT * FROM `transactions` LIMIT [page*num_records_per_page],[num_records_per_page];

e.g.: SELECT * FROM `transactions` LIMIT 0,25 ORDER BY Datetime; # First 25 records