2011年12月20日火曜日

[JavaScript]childNodes と children で子ノードを取得する

いまさらですが知らなかったのでまとめました・・

childNodesプロパティ


JavaScriptでDOMを利用した処理をする場合、あるノードの子ノードを取得し、その子ノードに対して何らかの処理を行うというのは、よくあるパターンです。
今までの記事でも、子ノードを取得する場合、下記のように、DOMのchildNodesプロパティを使って取得していました。

サンプルHTML
<ul id="sample_list">
    <li>this</li>
    <li>is</li>
    <li>a</li>
    <li>test</li>
</ul>

サンプルコード
var ul = document.getElementById("sample_list");
var ch = ul.childNodes;
for (var i = 0, len = ch.length; i < len; i++) {
    console.log(ch[i].nodeName);
}

実行結果(以下すべて Chrome 16 で実行)
#text //改行がTextNodeとして取得されている
LI
#text
LI
#text
LI
#text
LI

上記のサンプルのように、childNodesプロパティで子ノードを取得した場合は、全ての子ノードのcollectionが返されます。 全ての子ノードということは、当然TextNode も含まれるので、改行やスペースがノードとして取得されています。 

通常、子ノードに対して処理をする場合、TextNodeは無視したい場合がほとんどなので、子要素のcollectionをフィルタリングする必要があります。 

サンプルコード
var ul = document.getElementById("sample_list");
var ch = ul.childNodes;
for (var i = 0, len = ch.length; i < len; i++) {
    if (ch[i].nodeName === 'LI'){
       console.log(ch[i].nodeName);
    }
}

実行結果
LI
LI
LI
LI

childrenで代用


childNodes の代わりに、childrenを使うと、TextNode は含まない、要素ノードだけのcollectionが返されます。
childrenは、IE6をはじめほぼ全てのブラウザで実装されているため、クロスブラウザの対応は特に必要ありません。

 サンプルコード
var ul = document.getElementById("sample_list");
var ch = ul.children;
for (var i = 0, len = ch.length; i < len; i++) {
    console.log(ch[i].nodeName);
}

実行結果
LI
LI
LI
LI

他にも要素ノードだけを対象にしたDOM非標準プロパティとしては、firstElementChild, lastElementChild, nextElementSibling などがありますが、children以外はブラウザによっては実装されていない場合があるので、使用には注意が必要です。

まとめ


子ノードの取得には、children がつかえる!

参考文献
ハイパフォーマンスJavaScript p50
ハイパフォーマンスJavaScript
ハイパフォーマンスJavaScript

2011年12月15日木曜日

[JavaScript]option要素にdisabledを設定する

form内の複数のselect要素に対して、一方を選択すると、他方のselectのoptionが自動的に絞り込まれるという処理を、以下のサンプルHTMLに対して、JavaScriptを使って実現してみようと思います。

サンプルコード
<form>
    <select id="upper">
       <option value="1">first</option>
       <option value="2">second</option>
    </select>
   
    <select id="downer">
       <option value="1_1">first_first</option>
       <option value="1_2">first_second</option>
       <option value="2_1">second_first</option>
       <option value="2_2">second_second</option>
    </select>
</form>

仕様は、
  • id="upper" のselect要素のvalueと、id="downer"のselet要素の子のoption要素のvalueの1文字目を比較し、値が一致するdownerのoptionだけを、ユーザーが選択可能とする。
とします。

最初に作ったプログラム


最初に、条件に一致しないdownerのoption要素に、disabled属性を設定してみました。

サンプルコード
window.onload = function(){
    var upper_select = document.getElementById("upper"),
        downer_select = document.getElementById("downer");

        autoSelectOptions(upper_select, downer_select);
        upper_select.onchange = function(){autoSelectOptions(upper_select, downer_select)};
}

function autoSelectOptions(upper_select, downer_select) {
    var selected_value = upper_select.value,
        downer_ch = downer_select.childNodes,       
        first_hit_flag = true;

    for (var i=0, len=downer_ch.length; i < len; i++) {

       if (downer_ch[i].tagName && downer_ch[i].tagName === 'OPTION' ){

           downer_ch[i].disabled = true;  //一旦すべてのoptionを選択不可にする
           downer_ch[i].selected = false; //選択状態をリセットする

           if (selected_value === downer_ch[i].value.split('_')[0]) {

               downer_ch[i].disabled = false; //選択可能にする

               if (first_hit_flag === true) {
                   //一番上の選択可能optionを選択状態表示させる
                   downer_ch[i].selected = true;
                   first_hit_flag = false;
               }
           }
       }
    }
}

落とし穴にはまる


ふふふ、このくらい簡単々と調子に乗ってたら、このコードではIE6, 7では正しく動作しませんでした。IE6, 7 では、option要素にはdisabled を設定できないということが原因です。。

というわけで、IE6, 7にも対応したのが以下のコードです。 ポイントは、window のonload イベントが呼ばれたときに、id=downerのselect要素の子のoption要素に対してcloneNode()メソッドを呼び出し、optionのクローンを作成していることです。

autoSelectOptions関数が呼ばれるたびに、一旦downerのoption要素を全て削除してから、複製化しておいたoptionから、条件に一致する要素のみ挿入しています。

サンプルコード
window.onload = function(){
    var doc = document,
             upper_select = document.getElementById("upper"),
             downer_select = document.getElementById("downer"),
             downer_options = downer_select.childNodes,
             cloned_options = new Array();
       
   //初期表示されるdownerのoptionのクローンを保存しておく
   for( var i=0, len=downer_options.length; i < len; i++){
       if (downer_options[i].tagName && downer_options[i].tagName.toLowerCase() === 'option') {
           cloned_options.push(downer_options[i].cloneNode(true));
       }
   }

   autoSelectOptions(upper_select, downer_select, cloned_options);
   upper_select.onchange = function(){autoSelectOptions(upper_select, downer_select, cloned_options)};
}

function autoSelectOptions(key_select_box, target_select_box, option_list){

   if (typeof key_select_box    === 'undefined' ||
       typeof target_select_box === 'undefined' ||
       typeof option_list       === 'undefined') {
           return;
   }
   
   var first_node_flag = true,
       ch = target_select_box.childNodes;
       
   for (var i=ch.length - 1; i >= 0; i-- ){
       //selectの子ノードを一旦すべて削除する。
       ch[i].parentNode.removeChild(ch[i]);
   }
   
   var fragment = document.createDocumentFragment();
   for (var i = 0, len = option_list.length; i < len; i++) {
       
       if (option_list[i].tagName && option_list[i].tagName.toLowerCase() == 'option'){
           option_list[i].selected = false;
               
           if (option_list[i].value.split('_')[0] === key_select_box.value){
               fragment.appendChild(option_list[i]);
               if (first_node_flag) {
                   option_list[i].selected = true;//最初に挿入するノードを,選択状態にする
                   first_node_flag = false;
               }
           }
       }
   }    
   //documentに条件に一致するのoptionのみ追加
   target_select_box.appendChild(fragment);    
}
IE6, 7 ともに動作することを確認しました! 一旦option要素をすべてremoveするなどちょっと強引ですが、仕様は満たされてるので良しとします。

まとめ


  • IE6, IE7 では、optionのdisabled属性は、設定できないので注意する!

参照URL
Forms in HTML documents http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.6
Node.cloneNode - MDN https://developer.mozilla.org/En/DOM/Node.cloneNode

2011年12月1日木曜日

[jQuery]要素の大きさを取得する

Javascript を使って要素の大きさを取得する場合、要素に設定されているpadding, border などのスタイルの幅を考慮する必要がよくあります。
下のスタイルを適用された、div要素について、JavaScript と jQueryで高さを取得しながら、jQueryの便利メソッドについて確認してみます。

css
div#target{
    height: 100px;
    width: 100px;
    padding: 10px;
    margin: 10px;
    border: 1px solid #FFF;
    background-color: #CCC";
}


jQueryを使わないでやってみる


上のスタイルが適用された要素の大きさを、純粋なjavascriptで取得するには、window.getComputedStyle() (IE8ではcurrentStyle) メソッドを呼び出して、CSSStyleDeclaration オブジェクトを取得し、オブジェクトのgetPropertyValue()メソッドを使ってプロパティにアクセスします。(参照)
下の例だと、style.getPropertyValue("height")は要素そのものの高さのみ取得できるので、paddingやborderの幅を考慮する場合は、別途処理が必要になります。

var elem = document.getElementById('target');
var style = window.getComputedStyle(elem, null); // IE8では不可
alert( style.getPropertyValue("height") );              // 100px
alert( style.getPropertyValue("padding-top") );         // 10px
alert( style.getPropertyValue("padding-bottom") );      // 10px
alert( style.getPropertyValue("border-top-width") );    // 1px
alert( style.getPropertyValue("border-bottom-width") ); // 1px


jQueryを使ってシンプルに


jQueryを使えば、状況にあわせて、要素の大きさを簡単に取得できます。
例えば高さを取得する場合は、hight(), innerHeight(), outerHeight() が使えます。
それぞれのメソッドが返す値を、下のコードで確認してみました。

$( '#target' ).height();      //100
$( '#target' ).innerHeight(); //120 上下のpaddingの幅が含まれる
$( '#target' ).outerHeight(); //122 paddingの幅 + 上下のborderの幅が含まれる

上の実行結果から、
  • .height() は要素そのものの高さを返す
  • .innerHeight() はpadding を含む高さを返す
  • .outerHeight() はpadding に加えて、border の幅も含む高さを返す
  • .margin の値は影響しない

ということがわかりました。
もちろん以上の動作はwidth(), innerWidth(), outerWidth() でも同じです。


注意点


$(window)に対して innerWidth(), innerHeight(), outerWidth(), outeHeight() を実行すると、NaNが返されます。
window の大きさを取得したい場合は、$(window).height(), $(window).width() でOK。


まとめ


要素の大きさをjQueryで取得するには、
  • .height() で要素そのものの高さを
  • .innerHeight() で padding の幅を含めた高さを
  • .outerHeight() で padding と border の幅を含めた高さを取得できる!
(.width() .innerWidth() .outerWidth() も同様)


参考文献
jQueryクックブック p140
jQueryクックブック
jQueryクックブック

2011年11月29日火曜日

[JavaScript]要素のスタイル情報を取得する (window.getComputedStyle)

styleオブジェクトのプロパティ


インラインまたは動的に設定されるすべてのスタイルには、要素のstyleオブジェクトのプロパティからアクセスできます。
var position = elem.style.position

注意点としては、backgcounr-color のように、ハイフンが名前に含まれるプロパティについては、キャメルケースを使う必要があることです。('-' が減算演算子と解釈されてしまうため。)
var bgcolor = elem.style.backgroundColor;

また、上記の方法で取得できるのは、インラインで設定されたか、JavaScriptを使って動的に設定されたスタイル値だけなので、スタイルシートを使って設定されたスタイルにはアクセスできません。


スタイルの設定方法に関係なく、スタイルにアクセスする方法


スタイルシートを使って設定されたスタイルにアクセスするには、window.getComputedStyle()メソッドを使います。
このメソッドが返すのは、CSSStyleDeclaration オブジェクトで、オブジェクトのプロパティには、getPropertyValue()メソッドにプロパティ名を渡してアクセスします。このメソッドに渡すプロパティ名は、cssのプロパティと同じで、キャメルケースに変換する必要はありません。

※ getComputedStyle()メソッド古いIE(IE8よりも前)には実装されていないので、クロスブラウザ対応が必要になります。
var style = window.getComputedStyle(elem, null);
var bgcolor = style.getPropertyValue("background-color");

なお、getComputedStyle()メソッドは、document.defaultView からも呼び出せます。
var style = document.defaultView.getComputedStyle()


IE8では、要素のcurrentSytyle プロパティにアクセスしてスタイル値を取得します。
var style = elem.currentStyle

currentStyle オブジェクトのプロパティには、キャメルケースでアクセスします。
var bgcolor =  style["backgroundColor"];


サンプル(要素elemにスタイルシートで適用されているbackground-colorの値を取得する)


var style;
var bgcolor;
if (elem.currentStyle) { //クロスブラウザ対応
    style = elem.currentStyle;
    bgcolor =  style["backgroundColor"];

} else if (window.getComputedStyle) {
    style = window.getComputedStyle(elem, null)
    bgcolor = style.getPropertyValue('background-color');
}


取得されるスタイル値の優先順位


スタイルがインラインとスタイルシートを通じて設定されている場合は、インラインのスタイルが優先されます。
動的に設定されるスタイルは、インラインとスタイルシートで設定された値に関係なく、動的に設定されたスタイルが優先されます。


スタイルの設定


window.getComputedStyle()で取得できるオブジェクトは読み込み専用のため、JavaScriptでスタイルを動的に設定する場合は、要素のstyleオブジェクトのプロパティに直接セットします。(しつこいけどスタイル名はキャメルケース!!)
elem.style.backgroundColor = "#CCC";


まとめ


  • 要素のstyleプロパティからは、インラインまたは動的に設定されたスタイルのみアクセスできる。
  • 名前にハイフンが含まれるスタイルのプロパティ名は、キャメルケースに置き換えてアクセスする。
  • 設定方法に関係なく要素のスタイルを取得するには、window.getComputedStyle()メソッドを使う。(IE8以前はelement.currentStyle)
  • getComputedStyle() で取得したオブジェクトのプロパティには、getPropertyValue()メソッドを使ってアクセスする。

参照URL
window.getComputedStyle - MDN https://developer.mozilla.org/en/DOM/window.getComputedStyle
CSSStyleDeclaration - MDN https://developer.mozilla.org/en/DOM/CSSStyleDeclaration

参考文献
Javascript クックブック p252
JavaScriptクックブック
JavaScriptクックブック

2011年11月25日金曜日

[JavaScript] ブラウザで選択した文字列を取得

javascrpt を使って、ブラウザで現在選択されている文字列を取得する方法について確認してみます。

window.getSelection()で選択範囲を取得


windowオブジェクトのgetSelection() メソッドで、ブラウザで現在選択されている範囲をあらわす、Selectionオブジェクトが取得できます。

var selection = window.getSelection();


Selectionオブジェクトから選択された文字列を取り出すには、toString() メソッドを使います。

var selected_str = window.getSelection().toString();


なお、getSelection()メソッドはdocumentオブジェクトにも実装されているので、document.getSelection() としてもokです。


IE での対応(IE6 で確認)


IE ではwindow.getSelection()が実装されていないため、document.selectionプロパティを使います。このオブジェクトから文字列を取り出すには、createRange()メソッドを呼び出して返されるTextRange オブジェクトのtext プロパティにアクセスすればok です。


var selected_str = document.selection.createRange().text;


クロスブラウザ対応


クロスブラウザ対応としては、window.getSelection の有無で処理を分岐すればOK.

if (window.getSelection) {
    //IE 以外
} else {
    //IE
}

以上を踏まえて、「Shift key が押されたときに、選択されている文字列を表示する」プログラムを作成してみました。(動作はfirefox3.6, IE6 で確認しました。)

サンプルコード
<script type="text/javascript">
var win = window,
    doc = document; //グローバルオブジェクトをキャッシュ

win.onload = function(){
    var selected_str = '',
        SHIFT_KEY_CODE = 16;

    doc.onkeydown = function(evt){
        if (typeof evt === 'undefined') { //IE用にevent再設定
            evt = win.event;
        }

        if (evt.keyCode === SHIFT_KEY_CODE) {
            if (win.getSelection) {//クロスブラウザ対応
                selected_str = win.getSelection().toString(); //IE以外
            } else {
                selected_str = doc.selection.createRange().text; // IE
            }

            if (typeof selected_str !== 'undefined' && selected_str != '') {
                alert(selected_str);
            }
        }
    }
}
</script>

ここからさらに取得した選択文字列を 翻訳系 web API に渡すようにすれば、簡単な翻訳アプリなどに応用できそう!

まとめ


ブラウザの選択範囲の文字列を取得するには、

window.getSelection() メソッドを使う

IE ではdocument.selection.createRange().text でok

参照URL

window.getSelection - MDN https://developer.mozilla.org/en/DOM/window.getSelection

Selection - MDN https://developer.mozilla.org/en/DOM/Selection

selection Object http://msdn.microsoft.com/en-us/library/ms535869%28v=vs.85%29.aspx

TextRange Object http://msdn.microsoft.com/en-us/library/ms535872%28v=vs.85%29.aspx

2011年11月21日月曜日

[JavaScript] で要素の属性を取得する

基本はgetAttribute() / setAttribute() メソッド


setAttribute() / getAttribute() メソッドは、DOM標準、非標準を問わずすべての属性にアクセスできるため、要素の属性をset/get する時は常にこのメソッドを使うようにする。
var foo_id = document.getElementById("foo").getAttribute("id");

document.getElementById("foo").setAttribute("id", “new_id”);

class を扱う時の注意


例えばclass名を取得したい場合は、getAttribute("class") とすればよさそうだが、 IE7 ではgetAttribute("className") としないと、null が返されてしまう。(class属性はJavaScriptでアクセスするときの名前が変更されている属性のため)

ブラウザを問わず確実にclass名を取得するには、オブジェクトのclassNameプロパティに直接アクセスすればok。

//get
var foo_class = document.getElementById("foo").className;
//set
document.getElementById("foo").className = "newClass";

input要素の状態を表す属性


form のinput要素の状態を表す属性(disabled, checked など)についても、直接オブジェクトのプロパティにアクセスして設定,取得する。

var textbox = document.getElementById("textbox");
textbox.disabled = false;


jQueryの場合


jQuery では jQuery.attr() メソッドですべての属性にアクセスできる。
//get
var className = $("#foo").attr("class");
//set
$("#foo").attr("id", "newId");

class名をsetするときは、jQuery.addClass() メソッドを使う。
$("#foo").addClass("new_class" "other class");

まとめ


・要素の属性のget/setには、基本的に getAttribute() / setAttribute() メソッドを使う。

・例外的にclass名, formのinput要素の状態をget/setする際は、オブジェクトのプロパティに直接アクセスする。

・jQuery では、jQuery.attr() メソッドで要素の属性にアクセスする

参考文献:JavaScrip クックブック p251
JavaScriptクックブック
JavaScriptクックブック

2011年11月17日木曜日

[JavaScript] フォームの入力フィールドにオートフォーカスする

ページがロードされた時に、ユーザーIDや検索ワードなどの入力フィールドに自動的にフォーカスさせる方法について、javascriptとhtml5を使って確認してみます。
以下のサンプルhtmlについて、input id="focus_target" にオートフォーカスさせる場合を考えます。
htmlサンプル
<body>
<form>
<input type="text" id="focus_target" />
<input type="submit" />
</form>

<!-- 膨大なコンテンツ -->
<!-- 省略 -->
<!-- 膨大なコンテンツ -->
</body>

方法1. window のロードを待ってからfocus()メソッドを呼び出す


まず思いつく方法として、windowのロードが完了してから、要素のfocus()メソッドを呼び出す方法があります。
window.onload = function(){
    var target = document.getElementById("focus_target");
    target.focus();
}
ただしこの方法だと、ページのロード中にユーザーが別の入力フィールドフォーカスを移動させた場合、わざわざjavascriptが最初のフィールドにフォーカスが戻してしまうという、困った問題が発生する可能性があります。
なので、この方法はなるべく避けたいところです。
代替案としては、jQueryが使えるなら、
$(document).ready($("#focus_target").focus());
のようにdocumentのロード完了時にfocusすれば、ページ内のテキストがすべてロードされた時点でフォーカスが実行されますが、やはりサイズの大きなページや、遅いネットワークから接続している場合は、同じ問題が発生する可能性があります。

方法2.input要素の直下に<script>タグを挿入

上記の問題を回避する方法としては、自動フォーカスしたい<input>タグの直下に<script>タグを挿入する方法があります。
<body>
<form>
<input type="text" id="focus_target" />
<script>document.getElementById("focus_target").focus()</script>
<input type="submit" />
</form>
</body>
input要素がロードされた直後にfocus()を呼び出しているため、方法1. の問題は回避できます。

方法3.html5のautofoucs属性を適用する

HTML5では、すべてのフォームコントロールにautofocus属性が導入されました。
<input type="text" id="focus_target" autofocus />
html5のautofocusは単なるマークアップなので、すべてのブラウザで振る舞いが統一されます。ちなみにautofocus属性をサポートしていないブラウザは、単純にこれを無視するだけです。
以下の関数で,要素がautofocus属性を持っているか検証できます。
functiton supports_input_autofocus() {
    var i = document.createElement('input');
    return 'autofocus' in i;
}

まとめ


フォームの入力フィールドにオートフォーカスさせたい場合は、、

1. まずはhtml5のautofocus属性を設定しておき、autofocusをサポートしていない場合のみ、focus()を呼び出す
<body>
<form>
<input type="text" id="focus_target" autofocus />
<script>
if (!supports_input_autofocus()) {document.getElementById("focus_target").focus()};
</script>
<input type="submit" />
</form>
</body>

2. window の load が完了するのを待ってからfocus() するのはなるべく避ける

参考文献:入門 HTML5

入門 HTML5
入門 HTML5

2011年9月12日月曜日

[JavaScript] [jQuery] jQuery.find() と jQuery.children() で子(子孫)要素を取得する

jQuery を使って、jQueryオブジェクトの子要素、子孫要素をまとめて取得する場合、.find().children()メソッドを使います。このエントリでは、以下のネストした<ul id="nav"> について、li要素を取得しながら、2つのメソッドの違いを確認してみます。
(以下すべてのコードでは、jquery-1.6.2.js を使用して動作を確認しました。)
<ul id="nav">
<li class="toplevel">sport
<ul>
<li>soccer</li>
<li>bascketball</li>
</ul>
</li>
<li class="toplevel">technorogy
<ul>
<li>windows</li>
<li>Mac</li>
</ul>
</li>
</ul>

.find()は子孫要素を、.children()は直接の子要素を


.find()は、jQueryオブジェクトのすべての子孫要素に対して、引数で渡したセレクタ式にマッチする要素を取得します。

var lis = $("ul#nav").find('li');
console.log(lis.length); // 6 (#nav 以下のすべてのli要素が取得された)

これは,単純に$()にセレクタを渡した場合や、$()に引数を2つ渡した場合と同じです。

var lis = $('ul#nav li');

var nav = $('ul#nav');
lis = $('li', nav);

また、jQuery バージョン1.6 からは,jQueryオブジェクト,DOM elementでもfilterできるようになりました。

var toplevel = $("li.toplevel");

var nav = $('ul#nav');
var lis = nav.find(toplevel);
alert(lis.length); //2 (class="toplevel" のli が取得された。)

.children()は直接の子要素に対して、セレクタに一致する要素を取得します。

var lis = $("ul#nav").children('li');
console.log(lis.length); // 2 (#nav の直接の子要素のli要素が取得された)

これは,単純に$()にセレクタを渡した場合や、$()に引数を2つ渡した場合()と同じです。

var lis = $('ul#nav > li');

var nav = $('ul#nav');
lis = $('> li', nav);

まとめ


  • .find()はすべての子孫要素に対して、引数で渡したセレクタに一致する要素を取得する。
  • .children()は直接の子要素に対して、引数で渡したセレクタに一致する要素を取得する。
  • .find()には、jQueryオブジェクトやDOM element を渡すことができる。

※推奨されない記法


$()に2つの引数(selector, jQuery object)渡して、直接の子要素を取得する場合、">" で子要素を指定できますが、jQuery のドキュメントを見ると、この書き方は推奨されない(将来のリリースではサポートされない)ようです。(http://api.jquery.com/child-selector/)

var nav = $("ul#nav");
var lis = $("> li", nav); // 推奨されない記法

上のコードは、.children()を使って以下のように書き換えられます。

var lis = ("ul#nav").children('li');

2011年9月7日水曜日

[JavaScript] [jQuery] jQuery.extend()でオブジェクトをマージ(ミックスイン)する

オブジェクトのマージ(ミックスイン)


$.extend()に2つ以上の引数を渡すと、2つ目以降の引数で渡されたオブジェクトを、最初の引数で渡されたオブジェクトにマージすることができます。

以下のコードでは、hogeオブジェクト に fooオブジェクトをマージしています。

(以下すべてのコードでは、jquery-1.6.2.js を使用しました。)

var hoge = {name: "hoge", width: "100px" };
var foo  = {width: "200px", height: "100px"};

hoge = $.extend(hoge, foo);

console.log(hoge.name);   // hoge
console.log(hoge.width);  // 200px  <- foo.widthの値で上書きされた
console.log(hoge.height); // 100px <- foo.heightが追加された

$.extend()に引数が1つしか渡されない場合は、引数のオブジェクトは、$(=jQuery)オブジェクトにマージされます。

var hoge = {name: "hoge", width: "100px" };
$.extend(hoge);
console.log($.width); //100px

ネストしたオブジェクトをマージしたい場合は、最初の引数にtrue を渡せばokです。

var hoge = { pos: { top: "0", left: "0" } };
var foo  = { pos: { top: "100" } };

//------------------------------------------------------------------------
//true を指定しない場合
hoge = $.extend(hoge, foo);

console.log(hoge.pos.top);  // 100
console.log(hoge.pos.left); //undefined <- hoge.posはfoo.posに置き換わった

//------------------------------------------------------------------------
//true を指定した場合
hoge = $.extend(hoge, foo);

console.log(hoge.position.top);  // 100
console.log(hoge.position.left); // 0  <- hoge.position はfoo.posとマージされた

何が便利なのか?


例えば、ユーザーが上書きできるデフォルト値を持つ関数を作りたい場合、以下のように、$.extend()でoptionsオブジェクトをparamsとマージすれば、ユーザーが指定したオプション値をデフォルトのオプション値をミックスしたオブジェクトが出来上がります。

以降の処理では、optinsオブジェクトからすべてのオプションにアクセスできます。

function foo(params){

var options = {
top : 20,
left: 100
}

options = $.extend(options, params);
//---略---
}

まとめ


柔軟なオプション指定が可能な関数、jQueryプラグインを開発したいときは、$.extend()でデフォルト値とユーザー指定値をマージする!