DOCTYPE宣言はHTML、XHTMLがどのような仕様に沿って記述しているかを宣言する。
具体的には下記のように書く
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
ブラウザによって解釈は異なるが
基本的に
HTMLタグ以前にDOCTYPの宣言があれば
Stdrds="標準モード"=CSS 仕様に従った正しい解釈をするモード
で
・DOCTYPE宣言がない
・スペルミス、記述が省略されている
などの場合は
Quirks="互換モード"=
として解釈(レンダリング)される
また、XHTMLの宣言をする場合
通常,<?XML ...を一番先頭に記述するが
IE6ではこの記述がDOCTYPEより前にあるとQuirksモードとして
判断されてしまうのでXML宣言は省略して書く(エンコードがUTF-8であれば省略してもOKということになっている)
補足:XHTMLを使う場合の注意点
各部ブラウザのモードの識別については
ここなどにまとめられている
DOCTYPE スイッチについてのまとめと一覧表 (HTML 5 や IE 8 Beta 2 のモードスイッチなどの情報も含んだ 2008 年版 )
2009年5月28日木曜日
2009年5月27日水曜日
JavaScript arguments.callee
callee - MDC
現在実行している関数を示します。
無名関数内でcalleeを参照することで
無名関数であっても自身を参照できる
下のように、無名再帰関数を実行することができる
現在実行している関数を示します。
無名関数内でcalleeを参照することで
無名関数であっても自身を参照できる
下のように、無名再帰関数を実行することができる
function makeFactorialFunc() {
alert('making a factorial function!');
return function(x) {
if (x <= 1)
return 1;
return x * arguments.callee(x - 1);
};
}
var result = makeFactorialFunc()(5); // 120 (5 * 4 * 3 * 2 * 1) を返す
JavaScript @cc_on
一行で IE の JavaScript を高速化する方法
に@cc_onなんてのがあり
何者なのか調査
MSDNによると
@cc_on ステートメント
は"条件付きコンパイルの機能をアクティブにします。"とのこと
コメント/**/内に記述するので
@cc_onに対応していないブラウザでは、コメントとして無視される
JScriptの実装のようなので
対応するブラウザ=IEのみ
となる
下のようにすれば、IEとIE以外で実行するコードを分けられる
に@cc_onなんてのがあり
何者なのか調査
MSDNによると
@cc_on ステートメント
は"条件付きコンパイルの機能をアクティブにします。"とのこと
コメント/**/内に記述するので
@cc_onに対応していないブラウザでは、コメントとして無視される
JScriptの実装のようなので
対応するブラウザ=IEのみ
となる
下のようにすれば、IEとIE以外で実行するコードを分けられる
var type;
/*@cc_on
//IEのみ
type = "IE";
*/
//IE以外
type = "NOT IE";
JavaScript グローバル変数へのアクセスとパフォーマンス
一行で IE の JavaScript を高速化する方法
amachang の 「一行で IE の JavaScript を高速化する方法」を掘り下げてみた
などで書かれていたが
document、windowなどのグローバル変数へのアクセスは
パフォーマンスがよろしくない。
(latest logさんの速度比較は大変興味深い)
そこで、グローバル変数をローカル変数に代入し
アクセスする際はローカル変数にアクセスすることで
だいぶパフォーマンスが上がるみたい
jQueryでも同様の方法がつかわれている
prototype.jsでは使われておらず
普通にグローバル変数へアクセスしている
こういったあたりでjQueryの方が速度が速かったりしてるんだろう、きっと。
amachang の 「一行で IE の JavaScript を高速化する方法」を掘り下げてみた
などで書かれていたが
document、windowなどのグローバル変数へのアクセスは
パフォーマンスがよろしくない。
(latest logさんの速度比較は大変興味深い)
そこで、グローバル変数をローカル変数に代入し
アクセスする際はローカル変数にアクセスすることで
だいぶパフォーマンスが上がるみたい
var _doc = document;
jQueryでも同様の方法がつかわれている
// Will speed up references to window, and allows munging its name.
window = this,
prototype.jsでは使われておらず
普通にグローバル変数へアクセスしている
こういったあたりでjQueryの方が速度が速かったりしてるんだろう、きっと。
2009年5月26日火曜日
JavaScript 継承とプロトタイプチェイン
JavaScriptがプロトタイプベースのオブジェクト指向言語ってどういうこと?
まずは、擬似的な継承はこんな感じで実現できる
JavaScriptにおける全てのオブジェクトは
Object.prototypeを継承しています。
・constructor
・toString
・toLocaleString
・valueOf
・hasOwnProperty
・isPrototypeOf
・propertyIsEnumerable
などのメソッドがObject.prototypeに含まれる
後からObject.prototypeに追加もできる
まずは、擬似的な継承はこんな感じで実現できる
function Hito(name) {
this.name = name;
};
Hito.prototype.hello = function() {
alert('Hello! My name is ' + this.name);
};
function SuperMan(name) {
this.name = name;
}
//Hitoオブジェクトをプロトタイプに設定
SuperMan.prototype = new Hito();
var hulk = new SuperMan('Hulk');
//SuperManにhelloはないがプロトタイプチェインをたどり
//Hitoのhelloが見つかり実行される
hulk.hello();
JavaScriptにおける全てのオブジェクトは
Object.prototypeを継承しています。
・constructor
・toString
・toLocaleString
・valueOf
・hasOwnProperty
・isPrototypeOf
・propertyIsEnumerable
などのメソッドがObject.prototypeに含まれる
後からObject.prototypeに追加もできる
Object.prototype.hoge = function() {
alert('hoge');
}
"text".hoge();
JavaScript prototypeとメモリの関係
下の例では
Hitoコンストラクタから3つのオブジェクトを作成している
コンストラクタ内ではthisを使い、変数・関数を割り当てている
この場合だと、変数・関数ともにそれぞれ別にメモリ上に割り当てられてしまうことになり
メモリの無駄遣いとなる
そこでprototypeを使い
下のように書きかえることで
関数が共用されるようになる。
Hitoコンストラクタから3つのオブジェクトを作成している
コンストラクタ内ではthisを使い、変数・関数を割り当てている
この場合だと、変数・関数ともにそれぞれ別にメモリ上に割り当てられてしまうことになり
メモリの無駄遣いとなる
function Hito(name) {
this.name = name;
this.hello = function() {
alert('Hello! My name is ' + this.name);
};
}
var saito = new Hito('saito');
var ishii = new Hito('ishii');
var kume = new Hito('kume');
saito.hello();
ishii.hello();
kume.hello();
そこでprototypeを使い
下のように書きかえることで
関数が共用されるようになる。
function Hito(name) {
this.name = name;
};
Hito.prototype.hello = function() {
alert('Hello! My name is ' + this.name);
};
var saito = new Hito('saito');
var ishii = new Hito('ishii');
var kume = new Hito('kume');
saito.hello();
ishii.hello();
kume.hello();
JavaScrit スコープチェイン
JavaScriptクロージャを完全理解!スコープチェインを知る
を参考に勉強
ローカル変数を宣言した場合、JavaScript内部では
管理用のハッシュテーブル(変数オブジェクトと呼ぶ)
に格納される。
グローバル変数の場合はwindowオブジェクトのプロパティに格納される
例えば
という風にwindow.hogeでグローバル変数にアクセスできる
以下例ではグローバル変数にf()からアクセスできる
実行時、順にf()内の変数オブジェクトを検索しaはないので
次にグローバル変数を探し、アクセスしている。(関数外の変数にアクセスできる)
この変数の探索をスコープチェインという
を参考に勉強
ローカル変数を宣言した場合、JavaScript内部では
管理用のハッシュテーブル(変数オブジェクトと呼ぶ)
に格納される。
グローバル変数の場合はwindowオブジェクトのプロパティに格納される
例えば
var hoge = 100;
alert(window.hoge);
という風にwindow.hogeでグローバル変数にアクセスできる
以下例ではグローバル変数にf()からアクセスできる
実行時、順にf()内の変数オブジェクトを検索しaはないので
次にグローバル変数を探し、アクセスしている。(関数外の変数にアクセスできる)
この変数の探索をスコープチェインという
var a = 0;
function f() {
alert(a);
}
f(); // 0が表示される
JavaScript クロージャ
クロージャー
プログラミング言語において引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決する関数のことである。関数とそれを評価する環境のペアであるともいえる。この概念は少なくとも1960年代のSECDマシンまで遡ることができる。
まれに、関数ではなくとも、環境に紐付けられたデータ構造のことをクロージャと呼ぶ場合もある。
JavaScriptでのクロージャー
プログラミング言語において引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決する関数のことである。関数とそれを評価する環境のペアであるともいえる。この概念は少なくとも1960年代のSECDマシンまで遡ることができる。
まれに、関数ではなくとも、環境に紐付けられたデータ構造のことをクロージャと呼ぶ場合もある。
JavaScriptでのクロージャー
var cl = function() {
var counter = 0;
return function() {
counter += 1;
return counter;
};
};
var c = new cl();
alert(c()); //1
alert(c()); //2
alert(c()); //3
JavaScript apply呼び出し
第1引数で指定したオブジェクトをthisとし
また、第2引数で指定した配列を引数として
関数を実行する
また、第2引数で指定した配列を引数として
関数を実行する
var human = function(name) {
this.name = name;
}
function func1(pre) {
alert(pre + ' ' + this.name);
}
var h = new human('hoge');
//humanオブジェクトをthisとして['hello']を引数として
//func1を実行
func1.apply(h,['hello']);
JavaScriptスコープ
JavaScriptにおける変数のスコープは
ブロックスコープを持たず
関数内であれば、関数内のどの変数にもアクセスできる。
関数外からはアクセス不可
ブロックスコープを持たず
関数内であれば、関数内のどの変数にもアクセスできる。
関数外からはアクセス不可
var func = function() {
var a = 3, b = 1;
var inner = function() {
// var b = 7;とするとbは再定義され外側のbへは影響しない
b = 7; //外側の関数内の変数にアクセス可能
};
alert(b); //1
alert(a); //3
{
var a = 2;
}
alert(a); //2 ブロックスコープはないためaが上書きされる
inner();
alert(b); //7
};
var x = new func();
JavaScriptクラスとコンストラクタ
JavaScriptでクラス的なものを実現させるには
関数リテラルがクラスに相当するもので
関数リテラルをnewで初期化したものがインスタンスとなる
関数リテラルがクラスに相当するもので
関数リテラルをnewで初期化したものがインスタンスとなる
//関数リテラル(クラス)の定義
var animal = function(name) {
//thisは呼び出しものnekoオブジェクトの参照となる
this.name = name;
this.sayName = function() {
alert(this.name);
};
};
//newで初期化、オブジェクトの生成
var neko = new animal('tama');
neko.sayName();
JavaScript関数リテラル
JavaScriptにおいて関数はオブジェクト(Functionオブジェクト)となる
関数オブジェクトの表記方法には何種類かある
1つ目はfunction+関数名+引数()とする表記
もう1つは関数リテラルとして表記する方法
変数名 = function+引数とする
後者は無名関数と呼ばれるもので
前者の表記と比較すると
・関数名を与える必要がない場合、簡潔に書ける
・変数名、関数名の衝突を防げる
などのメリットがある。
また
のような書き方も可能
関数オブジェクトの表記方法には何種類かある
1つ目はfunction+関数名+引数()とする表記
function hoge(a) {
}
もう1つは関数リテラルとして表記する方法
変数名 = function+引数とする
var hoge = function(a) {
}
後者は無名関数と呼ばれるもので
前者の表記と比較すると
・関数名を与える必要がない場合、簡潔に書ける
・変数名、関数名の衝突を防げる
などのメリットがある。
また
var hoge = new function (a) {
}
のような書き方も可能
JavaScriptオブジェクトリテラル
オブジェクトは{}で囲み
プロパティ名、値(文字列、数値など)もしくは関数を設定する
プロパティ名、値(文字列、数値など)もしくは関数を設定する
//オブジェクトリテラル
var obj = {};
obj = {
name: 'hoge',
age: 30,
address: {
zip : 00-0000,
city : 'tokyo'
},
say : function() {
//関数
alert('yhaaa!');
}
}
//.プロパティ名でアクセス
alert(obj.name);
//[プロパティ名]でアクセス
alert(obj["address"].city);
//関数呼び出し
obj.say();
2009年5月25日月曜日
addEventListener
event.addEventListener
addEventListenerは
第一引数=イベントタイプを表す文字列(ex."click")
第二引数=EventListener インターフェースで実装されたオブジェクトあるいはJavaScriptの関数名
第三引数=falseの場合は子から親へ順番にイベントが伝播されるが、trueの場合は優先される。
第二引数の関数に引数を渡す場合、下の書き方ではダメ
渡す方法としては
無名関数として書く
だが、無名関数で書くと、removeEventListenerでイベントの削除ができない
下記のように、それぞれ名前付き関数で関数参照を保持すればよいのかな?
また、リスナーに登録できるのは
"EventListener インターフェースで実装されたオブジェクト"
ともあるので、以下のような書き方もできる(Firefox、OperaなどでIEではダメ)
上のやり方で、それぞれthisの挙動が異なるみたい
あとで
addEventListenerは
第一引数=イベントタイプを表す文字列(ex."click")
第二引数=EventListener インターフェースで実装されたオブジェクトあるいはJavaScriptの関数名
第三引数=falseの場合は子から親へ順番にイベントが伝播されるが、trueの場合は優先される。
第二引数の関数に引数を渡す場合、下の書き方ではダメ
document.getElementById('btn').addEventListener("click", doAlert('msg1'), false);
function doAlert(msg) {
alert(msg)
};
渡す方法としては
無名関数として書く
document.getElementById('btn').addEventListener("click", function(e) {doAlert('msg1')}, false);
document.getElementById('btn').addEventListener("click", function(e) {doAlert('msg2')}, false);
function doAlert(msg) {
alert(msg)
};
だが、無名関数で書くと、removeEventListenerでイベントの削除ができない
下記のように、それぞれ名前付き関数で関数参照を保持すればよいのかな?
var listener1 = function (event) { doAlert('msg1'); };
var listener2 = function (event) { doAlert('msg2'); };
document.getElementById('btn').addEventListener("click",listener1,false);
document.getElementById('btn').addEventListener("click",listener2,false);
また、リスナーに登録できるのは
"EventListener インターフェースで実装されたオブジェクト"
ともあるので、以下のような書き方もできる(Firefox、OperaなどでIEではダメ)
var listener1 = {
handleEvent : function (event) {
doAlert('msg1');
}
}
document.getElementById('btn').addEventListener("click",listener1,false);
上のやり方で、それぞれthisの挙動が異なるみたい
あとで
JavaScriptのイベント処理の書き方
1.HTMLタグ内の属性として記述する
この書き方だとメンテナンス性が落ちる、あと1つのイベントしか処理できない
2.elementオブジェクトのonXXXXに関数を定義する
1と同様に1つのイベントしか処理できない
3・addEventListener(IEではattachEvent)を利用する
複数のイベントを処理できる
Click
この書き方だとメンテナンス性が落ちる、あと1つのイベントしか処理できない
2.elementオブジェクトのonXXXXに関数を定義する
document.getElementById("btn").onmousedown = funciont(evt) {
evt = evt || window.event;
・
・
・
}
1と同様に1つのイベントしか処理できない
3・addEventListener(IEではattachEvent)を利用する
document.getElementById("btn").addEventListener('click', goFunc, false);
function goFunc(evt) {
evt = evt || window.event;
・
・
・
}
複数のイベントを処理できる
DIV要素の移動
2秒毎にDIV要素を下方向に10px移動させるJavaScirpt
var timerID;
$('runBtn').onmousedown = startDown;
$('stopBtn').onmousedown = stopDown;
//2秒ごとにgoDown()を実行
function startDown(){
timerID = setInterval("goDown()", 2000);
}
//Interverl処理をキャンセル
function stopDown() {
if (timerID) clearInterval(timerID);
}
function goDown() {
//offsetTopは親の座標軸を基準とした座標を返す
//offsetTopはreadOnlyのため
//div要素の座標変更にはstyle.topに代入する
//staticではstyle.topは無効のため、absoluteにする
$('boxA').style.position = "absolute";
$('boxA').style.top = $('boxA').offsetTop + 10 + 'px';
}
2009年5月22日金曜日
ブラウザのJavaScriptコールスタックサイズ
Safari3はスタックサイズがなんでこんなに少ないんだろう?
JavaScriptエンジンがNitroになったSafari4ではどうなのか
登録:
コメント (Atom)