Home > Tech
Tech Archive
False となる値 - JavaScript: The Good Parts
- 2008-12-26 (Fri)
- JavaScript
“JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス“の Appendix A に収録されている(であろう)表を引用しています。
False となる値
以下にあげる値は、if や switch の条件式の中で、false となります。
| Type | Value |
|---|---|
| number | 0 |
| number | NaN |
| string | ""(要素が空(から)の文字列) |
| boolean | false |
| Object | null |
| undefined | undefined |
意識/無意識のうちにでも理解しているとは思いますが、こうやって整理されているとまたわかりやすいですね。
さてここからは余談です。多くの言語では、文字列と配列は非常によく似た存在です。つまりどちらであっても、長さというプロパティがあって、添字によって中のデータに一つ一つアクセスできる、というものです。もし要素が空(から)の文字列が false であるなら、要素が空の配列はどうでしょう?実際には要素が空(から)の配列は false とは評価されません。おそらく JavaScript の Array は Object に帰するもので、空配列は null でない Object と云う意味で、例外になってしまうからでしょうか。
- Comments: 0
- Trackbacks: 0
Falsy values - “JavaScript: The Good Parts”
- 2008-12-26 (Fri)
- JavaScript
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.
- Comments: 0
- Trackbacks: 0
文字列比較 - JavaScript: The Good Parts
- 2008-12-23 (Tue)
- JavaScript
いつだったか、この blog にも何度か登場している Mauvis に勧められて購入した “JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス” は原書で何度か読みました。なんだか翻訳が最近出たそうなのですが(訳の問題はわかりませんが)、これはお勧めです。すごく薄いけど、気付かされることがすくなくとも、僕には沢山ありました。しばらくこの本から学んだことをいくつか紹介していきたいと思います。
最初は String の比較です。
以下の expression は共に true と評価されます。
('cat' == 'c' + 'a' + 't') // true
('cat' === 'c' + 'a' + 't') // true
この本を読むまでは、JavaScript はなんとなくインスタンスベースの比較をしてるのかなぁと思ってました。それはつまり、等号( == あるいは === )の左右両辺にが全く同じメモリアドレスを指し示している時だけ、true と評価される、ということです。しかし実際には、String の比較時はその文字列の内容を評価していました。
var s1 = s2 = 'foo'; var s3 = 'foo'; s1 == s2; // true s1 == s3; // still true, of course.
従って、もし万が一、インスタンスで文字列を比較したい場合は、以下のようにするといいでしょう。
var s4 = new String('foo');
var s5 = new String('foo');
s4 == s5 //false
しかし本の中になんども登場する通り(そして僕も強く同意しますが)、Wrapper Object (String, Number そして Boolean) は混乱の元です。必要となるシチュエーションもあまり想像できません。
ところでインスタンスベースの文字列比較、というのはもうあまりポピュラーではないんでしょうか?僕が多分最初に Java を学んだときはインスタンスベースの比較だったような気がしたのですが、今試してみたら (1.5.0_16 on Intel Mac) 内容で比較していますね。PHP も同じようです。
- Comments: 0
- Trackbacks: 0
String comparison - “JavaScript: The Good Parts”
- 2008-12-23 (Tue)
- JavaScript
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.
- Comments: 0
- Trackbacks: 0
configure your Sandbox with Scheme
- 2008-11-20 (Thu)
- Mac
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 に注目したいですね。
- Comments: 0
- Trackbacks: 0
Coway’s Game of Life
- 2008-11-14 (Fri)
- JavaScript
ライフゲームは思い入れがあるというか、僕が NYU で一番最初に自分で書き上げたプログラムです。セル・オートマトンというアイデアもとても面白いし、何より動いていくその様が大好きでした。ITP の最初の期末、発表の数時間前に書き上げて、動いていたのはとても感動的…なんて話はどこかに書いた気がします。どうってことないプログラムだけれど、やっぱり動くのをみるのは気持ちいいですよね。その発表したバージョンは、Macromedia Director Lingo で書かれていて、どうやったか覚えてないけど、マルチプレイヤーでした…3人まで参加できて、matrix のアニメーションを排他ロックしていたはず…
マルチプレイヤーの部分はまだ実装してませんが、一人遊びをする分にはこれで十分かと思います。お楽しみください。100分の1程度の割合で、セルが突然変異をするので色がだんだんかわっていきますよ。
インタラクションの制御に MochiKit を使っていますが、もうちょっと改良の余地はありそうです。
- Comments: 0
- Trackbacks: 0
モチキット入門
- 2008-11-13 (Thu)
- JavaScript
諸般の事情により、今更ですが MochiKit をはじめてみました。Prototype.js と jQuery にどっぷりだった人が全然違う vocabulary にすごい悪戦苦闘してる感じ。ただしばらく使ってみると、それなりに使いやすいのは解ってきたので、ごく初歩でつまずいたところを簡単に羅列しておきます。
- Mochikit ではなく MochiKit
このへんは、キャピタルレター好きのドイツ人感性だろうか… - MochiKit.js はローダー。
意味論的にメソッドがファイル (object) に分類されていて、MochiKit.js を読み込むと凡てのファイルを読み込む。選択的に使いたい場合は、<script>文を複数行書く。ただし、依存関係もあるので、MochiKit.MochiKit.SUBMODULES に書かれた順序で読み込むのが正しい感じ。 - global 汚染しない方法もある
jQuery な人が最初に気持ち悪いと思うのは、デフォルトでかなりの数の関数が global 名前空間に登録されていること。official のドキュメントの一番最初にあるが、<script type="text/javascript">MochiKit = {__export__: false};</script>を MochiKit 関連を読み込む前に発行しておけば、FQMN (Fully-Qualified-Method-Name: なんて言い方があるかどうか知らないが) のみのアクセスに制限できる。 - ドキュメントは expand all してページ内検索
語彙がだいぶ違うとはいえ、宇宙語ではないので多分全ての語彙からキーワードを検索すれば多分何かは解るはず。ドキュメントは Overview が時代遅れな感じがしますが、細かい部分の完成度は高いです。
前に作った、Conway’s Game of Life を MochiKit を使って書き直してみました。というか、EventRunner を使わなくなっただけとも言えます…
- Comments: 0
- Trackbacks: 0
Duck Typing on JavaScript, and getter/setter
- 2008-10-31 (Fri)
- JavaScript
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:
- Let A be a new array created as if by the expression new Array().
- Call the [[Get]] method of this object with argument "length".
- Call ToUint32(Result(2)).
- Call ToInteger(start).
- If Result(4) is negative, use max( (Result(3) + Result(4)), 0 ); else use min( Result(4), Result(3) ).
- Let k be Result(5).
- If end is undefined, useResult(3); else use ToInteger(end).
- If Result(7) is negative, use max( (Result(3) + Result(7)),0 ); else use min( Result(7), Result(3) ).
- Let n be 0.
- If k is greater than or equal to Result(8), go to step 19.
- Call ToString(k).
- 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.
- Call ToString(n).
- Call the [[Get]] method of this object with argument Result(11).
- Call the [[Put]] method of A with arguments Result(13) and Result(14).
- Increase k by 1.
- Increase n by 1.
- Go to step 10.
- Call the [[Put]] method of A with arguments "length" and n.
- 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…
- Comments: 4
- Trackbacks: 0
Process String
- 2008-10-28 (Tue)
- JavaScript
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.
- 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. - 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. - 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.
- Comments: 0
- Trackbacks: 1
Touch of Canvas, and Firebug Profiling
- 2008-10-26 (Sun)
- JavaScript
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.
- HTML5: Specification of Canvas tag
- Apple ADC: A list of methods you can use Webkit
- Apple ADC: Using Canvas
- Opera: Canvas support in Opera 9.5
- Mozilla MDC: Canvas
- HTML5.jp: Canvas Reference (this site is the best comprehensive one, but written in Japanese. Learn Japanese! ;P)
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!
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.
- Comments: 0
- Trackbacks: 0
Home > Tech
- Search
- Feeds
- Meta
- Links

