JavaScript の質問用スレッド FAQ

FAQ

開発者ツール(Developer Tools)の基本的な使い方を教えてください

諸注意

要素を検証

  1. ページ上で右クリックして [要素を検証]
  2. [Elements] パネルが開き、対象のDOMノードが選択される(選択対象が目的の要素でなければ [Elements] パネル上で選択し直す)
  3. 右側のサイドバーから知りたいステータス名のタブを選択する
    • [Styles] タブ … CSSプロパティの指定値を表示 (※カスケードによって上書きされたプロパティは取り消し線で表示される)
    • [Computed] タブ … CSSプロパティの算出値を表示("font-size: 1em" を指定していても算出後の "*px" で表示される)
    • [Properties] タブ … 選択したDOMノードのプロパティを表示

コンソール

  1. JavaScript コード上で console.log('Hello, World!'); と入力
  2. ショートカットキーを参考に [Console] パネルを開く
  3. [Console] パネルに "Hello, World!" と表示される

(※window.alert() は String 型に変換されますが、console.log() は Object 型の中身をそのまま表示してくれます。)

ショートカットキー

ブラウザ 機能 ショートカットキー
Google Chrome 開発者ツールを開く [Ctrl] + [Shift] + [I]
Google Chrome [Console] パネルを開く [Ctrl] + [Shift] + [J]
Firefox 開発者ツールを開く [Ctrl] + [Shift] + [I]
Firefox Web コンソールを開く [Ctrl] + [Shift] + [K]
Safari 開発者ツールを開く [Ctrl] + [Shift] + [I]
IE 開発者ツールを開く [F12]
"IE9+" や "IE8-" の単語の意味を教えてください
document.getElementById('Sample').firstChild を実行すると "TypeError: Cannot read property 'style' of null" の例外が発生するのですが

getElementById は要素が存在しない時に null を返す仕様の為、コード実行時点で #Sample の要素が読まれていない場合に発生します。

<script type="text/javascript">
document.getElementById('Sample').firstChild.data = 'replaced!';  // TypeError: Cannot read property 'firstChild' of null 
</script>
<p id="Sample">Sample text.</p>

addEventListener, attachEvent を使用してドキュメント読み込み完了後に実行する事で例外を回避できます。

<script type="text/javascript">
(function () {
  function handleLoad () {
    document.getElementById('Sample').firstChild.data = 'replaced!';                 // ドキュメント読み込み完了後なので例外は発生しない
  }

  if (document.addEventListener) {                                                   // モダンブラウザ(IE9以降含む)用
    document.addEventListener('DOMContentLoaded', handleLoad, false);                // DOM構築完了後(DOMContentLoaded)に呼び出す
  } else if (typeof attachEvent === 'object' || typeof attachEvent === 'function') { // IE8以下用
    attachEvent('onload', handleLoad);                                               // ドキュメント読み込み完了後(load)に呼び出す
  }
}());
</script>
<p id="Sample">Sample text.</p>

jQuery の jQuery(function () {}), jQuery(function () {})jQuery(document).ready(function () {}) でも DOMContentLoaded を実現できます。

window.open(), frame, iframe要素を参照したいのですが

参照先が同一ドメイン内であれば、下記コードで参照可能です。

/**
 * window.open()
 */
var win = window.open('test.html', '_blank');
var sample = win.document.getElementById('Sample'); // window.open() で開いた "test.html" 内の #Sample を参照する

/**
 * frame要素(※HTML5で廃止)
 */
var frame = window.frames['menu']; // frame[name=menu] を参照
var sample = frame.document.getElementById('Sample'); // frame要素の参照先ドキュメント内の #Sample を参照する

/**
 * iframe要素
 */
var iframe = document.getElementsByTagName('iframe')[0];
var sample = iframe.contentWindow.document.getElementById('Sample'); // iframe要素の参照先ドキュメント内の #Sample を参照する

参照先が異なるドメイン(クロスドメイン)であれば、window.postMessage()もしくは、XMLHttpRequest Standard とAccess-Control-Allow-Origin ヘッダをサーバに指定する事で参照可能です。

ローカルファイルを読み/書きしたいのですが

File API を使用して下さい。

<p onclick="foo()"> の onclick 属性内で foo(), bar() を同時に呼び出したいのですが

セミコロンで複数の文(Statement)を区切る事が出来ます。

<script type="text/javascript">
function foo (event) {
  alert(event.type + ': foo'); // "click: foo"
}

function bar (event) {
  alert(event.type + ': bar'); // "click: bar"
}
</script>
</head>
<body>
<p onclick="foo(event);bar(event);">Click Me!</p>
<!-- onclick 属性内では event オブジェクトを参照可能な為、関数呼び出し時に event オブジェクトを渡すことでイベントハンドラ関数 foo, bar でも event オブジェクトを扱うことが出来ます。 -->

addEventListener, attachEvent を使用する事で onclick 処理を外部スクリプト化することができます。


<!-- JavaScript からの参照目標とする為、id="Sample" を付与します。-->
<p id="Sample">Click Me!</p>

<script type="text/javascript">
(function () {                   // 無名関数で括ってグローバル汚染を回避します
  function foo (event) {         // addEventListener, attachEvent は listener 関数の第一引数で event オブジェクトを渡します
    alert(event.type + ': foo'); // "click: foo"
  }
  
  function bar (event) {
    alert(event.type + ': bar'); // "click: bar"
  }

  function init () {             // 初期化処理
    var p = document.getElementById('Sample');

    /**
     * (注意)
     *  - addEventListener は登録順の実行を保証する為、foo() -> bar() の順番で実行します。
     *  - attachEvent は実行順がランダムな為、foo() -> bar() の順番での実行を保証できません。
     *  - この性質上、attachEvent で同一要素の同じイベントタイプを登録する場合は実行順がランダムでも動作するようにコーディングする必要があります。
     */
    if (p.addEventListener) {    // モダンブラウザ用 (※IE9 から addEventListener に対応)
      p.addEventListener('click', foo, false);
      p.addEventListener('click', bar, false);
    } else if (p.attachEvent) {  // IE8-用 (※IE8- は addEventListener に未対応)
      p.attachEvent('onclick', foo);
      p.attachEvent('onclick', bar);
    }
  }

  init();                        // 初期化処理を呼び出します
}());
</script>

attachEvent の実行順を保証したい場合は一つの関数だけを登録するように修正します。

(function () {
  function foo (event) {
    alert(event.type + ': foo');        // "click: foo"
  }
  
  function bar (event) {
    alert(event.type + ': bar');        // "click: bar"
  }

  function foobar (event) {             // foo(), bar() を呼び出す foobar() を定義します
    foo(event);
    bar(event);
  }

  function init () {
    var p = document.getElementById('Sample');

    if (p.addEventListener) {
      p.addEventListener('click', foobar, false);
    } else if (p.attachEvent) {
      p.attachEvent('onclick', foobar); // attachEvent に一つしか登録しない為、実行順ランダムの問題は発生しません
    }
  }

  init();
}());
document.write() でページ内容を追加したいのですが…
一度ページ表示完了後に document.write() すると内容はクリアされちゃいます。
部分的に内容変更するには document.write() 以外の方法にしましょう。
  1. 他フレーム/iframe/別窓への表示
  2. textarea等への表示
  3. Node#appendChildNode#insertBefore でノード挿入
  4. innerHTML (IE/Gecko/Webkit/Opera で実装されているデファクトスタンダードなプロパティ。HTML5 で標準化する見込み。)
IE9- でtable/tbody/tr要素のinnerHTMLによる書き換えが出来ないのですが
IE9- における table/tbody/tr要素の innerHTML は読み取り専用です(IE10 で修正済)。DOMを使って書き換えるか、<table> の親要素の innerHTML を書き換えましょう。
<div id="Sample"><table><tbody><tr><td>sample</td></tr></tbody></table></div>
<script type="text/javascript">
document.getElementById('Sample').innerHTML = '<table><tbody><tr><td>Replaced!</td></tr></tbody></table>';
</script>
DOMでtable要素にtr要素を追加しても表示されないのですが…
DOMでは(XHTML 1.x除く)tbody要素にtr要素を追加する必要があります。
tbody要素はtbodyタグを書いていなくても自動的に作成されます。
または HTMLTableElement/HTMLTableSectionElement で insertRow() を使いましょう。
変数 w1, w2, w3 ... を順にループで(番号をiに入れて)設定/参照したいのですが…
グローバル変数window のプロパティだから window['w'+i] を読み書きすれ。
input要素等のform関連要素を参照する方法を教えてください

下記コードを使用して下さい。

<form id="Sample">
  <p><input type="text" name="nickName" value="Ken"></p>
</form>
<script>
alert(document.getElementById('Sample').elements['nickName'].value); // "Ken"
alert(document.getElementById('Sample').elements.nickName.value);    // "Ken"
</script>

elements['nickName']elements.property と書く事も出来ます。

<a href="http://example.com/" onclick=""> で動作指定してるのですが時々動きません…
return false; でデフォルトアクションを抑制しないとページ移動してしまいます。
<a href="http://example.com/" onclick="return false;">sample</a>
event.preventDefault() もしくは event.returnValue でもデフォルトアクションをキャンセルできます。
<a href="http://example.com/" onclick="event.preventDefault ? event.preventDefault() : event.returnValue = false;">sample</a>
link要素,style要素で設定した背景色が element.style.backgroundColor で取得できないのですが…
document.defaultView を経由して、getComputedStyle() を使う必要があります。
IE8- は getComputedStyle() に対応しないので、element.currentStyle を使います。
function getComputedStyleMod (element /*, pseudoElt*/) {
  var view, pseudoElt;

  view = element.ownerDocument.defaultView;
  pseudoElt = arguments.length > 1 ? arguments[1] : '';

  if (view && view.getComputedStyle) {
    return view.getComputedStyle(element, pseudoElt);
  }

  if (element.currentStyle) {
    return element.currentStyle;
  }

  throw new ReferenceError('getComputedStyle or currentStyle is not defined');
}
100*1.15 の結果が 114.999... となってしまうのですが…
ECMAScript の浮動小数点演算には丸め誤差があります。誤差を発生させたくない場合は整数演算にしてください。
alert(100*1.15);    // 114.99999999999999
alert(100*115/100); // 115
任意のデータをサーバ(別鯖ではない)から取り寄せたいのですが…
IE7+/Gecko/Webkit/Opera は XMLHttpRequest()、IE6- は ActiveXObject() を使えばできます。古いブラウザだと隠しフレームに読むなどのワザが必要。
var xhr;

if (typeof XMLHttpRequest === 'function' || typeof XMLHttpRequest === 'object') {
  xhr = new XMLHttpRequest();
} else if (typeof ActiveXObject === 'function' || typeof ActiveXObject === 'object') {
  try {
    xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0');
  } catch (e) {
    try {
      xhr = new ActiveXObject('Msxml2.XMLHTTP.3.0');
    } catch (e2) {}
  }
}
IE7- で setAttribute('class', 'foo'), setAttribute('onclick', 'bar()') が機能しないのですが
IE7- では setAttribute() はDOMプロパティへのセッターとして働きます。(IE8 で修正済み)
element.className および element.onclick で対応してください。
function bar () {
  alert('bar');
}

function init (element) {
  element.className = 'foo';
  element.onclick = bar;
}

init(document.getElementById('Sample'));
複数の関数を呼びたいときは複数の関数を呼び出す関数を定義しましょう。
function hoge () {
  foo();
  bar();
}

function init (element) {
  element.onclick = hoge;
}

init(document.getElementById('Sample'));
window.setTimeout() やイベントハンドラ関数に設定するコードに this を含めたいのですが

イベントハンドラ関数における方法は3つあります。

/**
 * (方法1) this 値を変数束縛する
 */
function Hoge (value) {
  this.value = value;
}

Hoge.prototype.setHandler = function () {
  var thisArg = this;                          // this値をローカル変数「thisArg」に束縛する

  document.addEventListener('click', function (event) {
    console.log(this === document);            // true
    console.log(this === event.currentTarget); // true
    console.log(thisArg.value);
  }, false);
};

var hoge = new Hoge('Hello');
hoge.setHandler();

/**
 * (方法2) Function.prototype.bind で this 値を束縛する
 */
function Piyo (value) {
  this.value = value;
}

Piyo.prototype.setHandler = function () {

  document.addEventListener('click', function (event) {
    console.log(this === piyo);                // true
    console.log(this === event.currentTarget); // false
    console.log(this.value);
  }.bind(this), false);
};

var piyo = new Piyo('Hello');
piyo.setHandler();

/**
 * (方法3) addEventListener の handleEvent を利用する (※attachEvent では利用不可)
 */
function Foo (value) {
  this.value = value;
}

Foo.prototype = {
  handleEvent: function (event) {
    console.log(this === foo);                 // true
    console.log(this === event.currentTarget); // false
    console.log(this.value);
  },
  setHandler: function () {
    document.addEventListener('click', this, false);
  }
};

var foo = new Foo('Hello');
foo.setHandler();

window.setTimeout, attachEvent では handleEvent 以外の方法を使用することになります。

文字列の置き換えをするときにコードを使いたい(Perlのs///e)のですが…
String#replace() を使いましょう。
var string = 'Hello, World! Hello, World!';
string = string.replace(/(Hello), (World)/g, function (subString, p1, p2, offset, sourceString) {
  console.log(subString);    // マッチした文字列全体
  console.log(p1);           // 1つめの () でキャプチャされた値
  console.log(p2);           // 2つめの () でキャプチャされた値
  console.log(offset);       // マッチした位置(オフセット)
  console.log(sourceString); // マッチした時点での string 値

  return 'Replaced';
});
console.log(string);         // Replaced! Replaced!
input type="file"の値を設定(参照)できないのですが…
セキュリティ制約のため設定は絶対に不可。参照はブラウザにより不可。