Home > Tags > english

english

Falsy values - “JavaScript: The Good Parts”

This entry is a note from “JavaScript: The Good Parts” on page 106, Appendix A: Awful Parts.

Falsy Values

In JavaScript, following values are considered as “false” when they come to conditional expression.

Type Value
number 0
number NaN
string ""(empty string)
boolean false
Object null
undefined undefined

You must have understood them already, but it’s good to have it organized.

In most of languages, String and Array is very similar. I mean, both instances have a length property for nature and you can access stored values by their own indexes. So I was wondering, if an empty string is falsy, why not an empty array is? No, an empty array is not falsy. I guess its because an array is acutally an object. Try typeof operator with one.

Here, I tried to evaluate an array with JavaScript’s nature, duck typing, but well, it doesn’t work as I imagined.

var a = [];
console.log( a ? 'true' : 'false'); //of course, true;

console.log( (String.prototype.constructor.apply(a)) ? 'true' : 'false'); //Oh? false... so..?

var b = ['b'];
console.log( (String.prototype.constructor.apply(b)) ? 'true' : 'false'); //still false...

Any value, even if it’s a string type of a String wrapper object, passed to string constructor makes an empty string.

String.prototype.constructor(['a']);

will do more as what you can imagine. String.prototype.constructor will run .valueOf() on the argument.

String comparison - “JavaScript: The Good Parts”

I’ve read “JavaScript: The Good Parts” a few times already, since it’s a thin but dense book. This book is somehow basic, but full of discerning. I should have do an Advent Calendar-ish thing if I could start this earlier.. But anyway, I will keep writing a bit about what I learned from this book for a while.

So the first thing, is a string comparison, on Chap. 2, page 10.

Following expressions both return true!

('cat' == 'c' + 'a' + 't') // true
('cat' === 'c' + 'a' + 't') // true

Before I read this, I originally thought JavaScript might compare the instance-base equality. I mean if the string instances on both side on the equal sign were pointing to the exactly same memory address, it would return true, but it is actually comparing its value.

var s1 = s2 = 'foo';
var s3 = 'foo';
s1 == s2; // true
s1 == s3; // still true, of course.

So, if you wanna do instance base equality, do as follows:

var s4 = new String('foo');
var s5 = new String('foo');
s4 == s5 //false

But as it’s mentioned in the book (and I strongly agreed!), wrapper objects (String, Number and Boolean) are just seeds of confusion. I don’t also see the neccessity of using them.

By the way, I thought that instance-base comaprison is more popular rather than value-base comparison. But as far as I just tested, Java (1.5.0_16 on Intel Mac) compares value, PHP compares value.. that’s intereting.

configure your Sandbox with Scheme

Mac OS X - from the server room to your desktop

[EN] / JA
BSD’s Jordan talks about inside Mac OS X. People just talk about the (future) release date of Snow Leopard, but I think more interesting thing is that… On page 29, as Sandbox Profiling language, they use Scheme!

EN / [JA]
FreeBSD の著名な開発者 Jordan Hubbard が Mac OS X の内部についてプレゼンテーションをし、その中で次期リリースについてふれらているのが話題になっていますが、僕はそれよりも、29ページ目にある、Sandbox Profiling 言語として使用されている Scheme に注目したいですね。

Duck Typing on JavaScript, and getter/setter

My friend Mauvis brought me (ahem) an interesting problem again.

Write a one-line piece of JavaScript code that concatenates all strings passed into a function: 

function concatenate (/*any number of strings*/) {
  var string = /*your one line here*/
  return string;
}

So, the first thing I’ve tried was as follows:

function concatenate () {
  var string = (function (a) {var r = [];for (var i = 0, len = a.length; i < len; ++i}{ r[i] = a[i]}return r.join('');)(arguments);
  return string;
}

I know that doesn’t look good. And it’s just in one line, but it’s actually a few lines.

Then Mauvis replied me back..

function concatenate () {
  var string = function(a){return Array.prototype.slice.call(a).join('');}(arguments);
  return string;
}

and eventually it bacame like this.

function concatenate () {
  var string = Array.prototype.join.call(arguments, '');
  return string;
}

This is a pretty interesting topic in JavaScript. The first one I did is pretty straight forward, right? Arguments object is an array-like object, that each local (function) space has automatically. You can iterate like an array. So I loop through each value, put it all together in a different array, then construct a new string.

The second one and third one are a bit unusual for the first look. What it does is apply Arguments object as an array in order to call slice or join method, which both of them are originally Array’s prototype methods.

If you are fuzzy about it, Let’s take a look the specification of JavaScript.

It’s a little too long, but I quote an entire section of slice (Page 105 - 106) here.

15.4.4.10 Array.prototype.slice(start, end)

The slice method takes two arguments, start and end, and returns an array containing the elements of the array from element start up to, but not including, element end (or through the end of the array if end is undefined). If start is negative, it is treated as (length + start) where length is the length of the array. If end is negative, it is treated as (lengt+ end) where length is the length of the array. The following steps are taken:

  1. Let A be a new array created as if by the expression new Array().
  2. Call the [[Get]] method of this object with argument "length".
  3. Call ToUint32(Result(2)).
  4. Call ToInteger(start).
  5. If Result(4) is negative, use max( (Result(3) + Result(4)), 0 ); else use min( Result(4), Result(3) ).
  6. Let k be Result(5).
  7. If end is undefined, useResult(3); else use ToInteger(end).
  8. If Result(7) is negative, use max( (Result(3) + Result(7)),0 ); else use min( Result(7), Result(3) ).
  9. Let n be 0.
  10. If k is greater than or equal to Result(8), go to step 19.
  11. Call ToString(k).
  12. If this object has a property named by Result(11), go to step 13; but if this object has no property named by Result(11), then go to step 16.
  13. Call ToString(n).
  14. Call the [[Get]] method of this object with argument Result(11).
  15. Call the [[Put]] method of A with arguments Result(13) and Result(14).
  16. Increase k by 1.
  17. Increase n by 1.
  18. Go to step 10.
  19. Call the [[Put]] method of A with arguments "length" and n.
  20. Return A.

The length property of the slice method is 2.

NOTE

The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object is implementation-dependent.

And here’s join section (page 103). This one is snippet.

15.4.4.5 Array.prototype.join (separator)

The elements of the array are converted to strings, and theses trings are then concatenated, separated
by occurrences of the separator. If no separator is provided, a single comma is used as the separator. The join method takes one argument, separator, and performs the following steps..

…(snip)…

NOTE

The join function is intentionally generic; it does not require that its this value bean Array object. Therefore, it can be transferred to other kinds of objects for use as a method. Whether the join function can be applied successfully to a host object is implementation-dependent.

Both sections consist of definition, procedures, and note. And interesting thing is on the Note: intentionally generic and implementation-dependent. So it depends on Browser dev, to implement it generic or not..

I made a page to try out those things: Duck Typing test.

And acutally, as it’s written on SPEC, you can use slice/join for your own object. What it’s written on 2 and 14 on Array.prototype.slice procedure, it needs to access [[Get]], which is an internal method for each object (page 26 - 28). According to John Resig’s JavaScript Getters and Setters, it can be used in Firefox, Safari and Opera. But as far as I tried, it doesn’t work in Opera. If IE has the other way to do it, I will be more interested in…

Process String

My good friend Mauvis was writing on his blog about to convert a string to comma separated ascii numbers. I commented there about his code. Here’s how I wrote, and also see his original: String.toCharCode().

String.prototype.toCharCode = function()
{
  var str = this.split('');
  var len = str.length;
  var work = new Array(len);
  for (var i = 0; i < len; ++i)
  {
    work[i] = String.charCodeAt(str[i]);
  }
  return work.join(',');
}

It was his quick hack for the day, I suppose, but it turns out to be very interesting thing to me. There are a few points to write faster code.

  1. explicit length of for loop — dot access considered harmful at least for speed.
    for JavaScript, .(dot) access is always very slow. Some people do like… for (var i = 0; i < arr.length; i++). That’s not good. On this case, i need to use array length twice so I made a local variable. The local variables are always the fastest access.
  2. NO for…in for Array
    for…in is basically built for Object enumeration. By using for…in, JavaScript will pass all properties with the internal DontEnum attribute false, to i (or accessor whatever you name). MDC:Object.propertyIsEnumerable() is very interesting to read about this topic.
  3. Do not concatenate a string
    In most of languages, string is immutable. In my early life of programming, I always wondered.. what’s the hell? Immutable? As its meaning, string is not changeable. but let’s see like…
    var s = "foo";
    s = "bar";
    alert(s); // returns "bar"!

    right? You can change it. But as a lower process level point of view, the code above is same exact meaning as follows.

    var s = new String("foo");
    s = new String("bar");
    alert(s); // returns "bar"!

    Two instantiation process. Now you believe me, right? This article: HotRubyがC Rubyより速い本当の理由は? (written in Japanese) explains very comprehensively how JavaScript engine would implement it. At least you should take a look at this picture. But overall, String concatenation considered harmful. In most cases, you can use Array.join() to connect multiple strings.

These looks very minor and small changes. But it does make a difference.

Touch of Canvas, and Firebug Profiling

Firebug Profiler

These days, I work on Canvas Animation with JSTweener to make an animation by JavaScript. Now you can see it on the new home page of my site. Check it out and give me some comments, please.

So in this entry, I’d like to give a brief introduction of Canvas and how to do profiling in JavaScript with Firebug.

Canvas

Canvas is a (relatively) new HTML Element where you can draw pixels by JavaScript, originally developed by Apple, and adopted in Web Standard as HTML5. It has a nice set of drawing APIs, similar to Processing drawing APIs. The way it handles transformation looks more similar to Processing/OpenGL style.. Like to push translated matrix you can call context.save(), and to pop it context.restore(), stuff like that.

There seems to be no comprehensive Canvas 2D APIs yet online in English, it may be bacuase it’s still ongoing implementation, and there’s slightly difference to each browser… So I just list up some links that I used.

And, as defacto standards, Internet Explorer doesn’t support Canvas yet. But wait! Canvas is not yet useless because of that! Google released a JavaScript library called explorercanvas. It has several of disadvantage, but it’s still good enough to offer the way to handle it. I’m wishing both Microsoft will make it happen and other Open source people will make explorercanvas better in future..

Animation and Profiling

Because I wanna do some animation on Canvas, I need 1) an animation engine and 2) massive optimization for speed. jQuery has easing plugin and seems to be available already in the core release, but… Hmm.. I just don’t feel like touching by glimpse at its document. Maybe next time.

I used JSTWeener for this time, which is a ported version of ActionsScript’s Tweener, originally developed by Zeh, and ported by Yuichi. Yet JS version doesn’t have some functionalities such as…Tweener.removeTweens() equivalent, still it has an advantage of ease of use as Tweener does, and it is stable.

Then I wrote some functions to draw vectors and image on canvas. I re-realized that my development machine is relatively faster than average ones! :P It doesn’t do animation on other machines.

Profiling really helps in that situation. And luckily, Firebug has a profile functionality. Just call console.profile("arbitrary title") to start, console.profileEnd() to finish profiling. The first picture is the result of profiler, it shows in Firebug console, you can change sort keys, and sort order.

It works pretty well in Firefox 3 + Firebug 1.2 (both latest version at this time).

But in some environment, it does NOT seem to work. I couldn’t run profier in Windows XP + Firefox 2 + Firebug 1.2 on VMWare. I found a discussion Problem using console.profile, and the author(?) says that you need to call loadFirebugConsole() before hand. It enabled me to call console.profile(), but afterwards I still could not stop profiling.. So I just installed Firebug 1.3 beta and it works although it gave me lots of crashes eventually.

jQuery.elementData() and event

Three weekends ago, my friends and I went to jQuery Camp 2008 at MIT. It was in Boston at the MIT Stata Center on Sunday, September 28th. I have been to Boston a few times, but I never been inside MIT (technically, it’s in Cambridge, which is different city than Boston…), and Stata Center was a beautiful Frank Gehry’s building.

And those friends who I went with are in the group called Flax, which I organized for young Design/Programming professionals around New York city area. We meet up every month and drink beers, talk about what’s interesting, and give one presentation every month.

So this entry is from my presentation at October Flax, about what I recently learned from jQuery Camp 2008.

_0012318 In the second presentation John Resig gave at jQuery Camp, he was talking about several cool stuffs,

_0012329and jQuery.data() appeals to me a lot because I have done very similar thing! He called elementData(), but on the syntax, you do like jQuery.data(). What it does is bascially dictionary (more CS-precisely it is a Set or Associative array). You can store data with key under certain DOM Element. Though it seems no ways to fetch what vocaburary it has (like.. getAllKeys()). So I take this as a name-spaced dictionary designed for event handling. Why? That’s how my presentation goes.

Module aware design

Let’s start with how I get to think like this way. When you do Event in HTML, there’s several ways to do it. You can do <body.onload="do();">, or document.body.addEventListener('click', function(){do()}, false);. If you’re using prototype, you can do Evnet.observe(). In jQuery, you can do either $(document.body).bind('click'...); or $(document.body).click(...);. The issue is, either one of ways, when the event happens, the function context will be different, in other words, “this” keyword points different object.

page1 Let’s see the world situation. Like in this picture, you wanna add Drop-down menu on each <li> tag. What I originally did was..

  1. build a Controller Object to each page
  2. then made a dictionary object in Controller Object
  3. register functions associated with each <li> in dictionary
  4. register events wrapping by this Controller’s event receiver
  5. every time event happens, it will lookup dictionary where the event happens

It works pretty well, until some point.

page2 As this picture, if you have subsidiary (child) elements in <li> elements, what will happen? When the event happens, browser fires an associated function with a first argument as DOMEvent, and that has .target property. Why that is important? Because I used it as a key to look up the dictionary. But as shown in this picture, the targe might be different from what it was originally registered. I needed to tweak it by the event receving process, that was not beautiful.

Then, I listened to John Resing’s presentaiton, jQuery.elementData() idea. I can use this as dictionary and I can write wrapper function. My answer is building EventRunner.js.

  1. First you will register your event like this: EventRunner.register(dom, ‘click’, obj.click, obj)
  2. EventRunner actually register event with wrapping by EventRunner.receiveEvent()
  3. if it’s Firefox or Safari, just pass the .currentTarget object to EventRunner.perform()
  4. if not, use EventRunner.ascendEvent() will happen recursively…

Here’s some demos.

var EventRunner = {}

EventRunner.MAX_DEPTH = 5;

EventRunner.ascendEvent = function (ev, elm, counter)
{
  counter = counter || 0;
  //console.log(counter + ': ' + elm.tagName);
  if ((elm.tagName.toUpperCase() === 'BODY') || (counter > EventRunner.MAX_DEPTH))
  {
    console.log(counter + ': ' + elm.tagName);
    return false;
  }
  if (!EventRunner.perform(elm, ev))
  {
    EventRunner.ascendEvent(ev, elm.parentNode, ++counter);
  }
}

EventRunner.perform = function (elm, ev)
{
  var result = false;
  var value  = jQuery.data(elm, ev.type);
  if (value instanceof Function)
  {
    try
    {
      result = {'result': value(ev)};
    }
    catch (err)
    {
      console.log('error occurs');
      console.log(err);
      //alert(err.message);
    }
  }
  else if (value !== null)
  {
    result = value;
  }
  return result;
}

EventRunner.receiveEvent = function (ev)
{
  if (ev.currentTarget)
  {
    EventRunner.perform(ev.currentTarget, ev);
  }
  else
  {
    EventRunner.ascendEvent(ev, ev.target);
  }
}

EventRunner.register = function (dom, type, func, context)
{
  if (!dom)
  {
    throw new Error('You have to pass DOM Object');
  }
  if (context)
  {
    func = EventRunner.scope(context, func);
  }
  if (dom === window)
  {
    $(dom).bind(type, func);
    return;
  }
  jQuery.data(dom, type, func);
  $(dom).bind(type, EventRunner.receiveEvent);
}

EventRunner.scope = function (target, func)
{
  return function ()
  {
    func.apply(target, arguments);
  }
}

Please stop using my email address as yours!

I don’t know how to send this message to somebody who I don’t know… but there’s (seems to be) a woman, whose name is BEATA K____, who seems to live in Virginia… I guess she (and/or some others) keeps using my email address as hers, which is somehow understandable, I guess she sometimes just confuses… My Email address is beatak@gmail.com, and her name Beata K.

A few years ago, I notice that some polish women have tendency to use my long term handle name beatak because of that reason… That’s fine for her personal account, but sorry, internet is basically first come first serve society and on Google, beatak is my account name… I mean seriously, you know your name, right? So please know your email address accurately! Please!!

Picture Post Card (Working title)

Picture 5

Picture Post card is a slideshow application running on your web browser. It will pick up good pictures from Flickr based on where you’re located. It’s still very much in beta, it may change lots of things. I will appreciate if you can share your comments or thoughts with me.

R.I.P. Dr Randy Pausch

Randy Pausch Inspired Millions

 I don’t know how to say “thank you and good luck” to Dr Pausch. I don’t know him personally, but I watch his video and read his “The Last Lecture” (you can throw me a stone now.) And that book instantly became one of my all time recurring book (though I know there might be critique about it. I would still say that the book is great) and that did drive me come back this place I think. I was en l’enfer for a while, right after I watched that video.

He did inspire me. I wished I had a luck to see him. I should write a letter to him.

Rest in peace, Dr Pausch, and hope Pausch Family great luck.

Home > Tags > english

Search
Feeds
Meta
Links

Return to page top