JavaScriptで多重継承もどき

コンストラクタ関数内で継承したいクラスのコンストラクタ関数を下記のように実行すると"多重継承のようなもの"ができるようです。

参考 : No Multiple Inheritance - MDC

//継承元1
function SuperClass1(prop1) {
 this.prop1 = prop1;
};

//継承元2
function SuperClass2(prop2) {
 this.prop2 = prop2;
};

//子クラス
function SubClass(prop1, prop2, prop3) {

 //多重継承
 this.superClass1 = SuperClass1;
 this.superClass1(prop1);
 this.superClass2 = SuperClass2;
 this.superClass2(prop2);
 
 this.prop3 = prop3;

};

var subClass = new SubClass("a", "b", "c");

console.log( subClass.prop1 ); // a
console.log( subClass.prop2 ); // b 
console.log( subClass.prop3 ); // c

通常の継承

//  親クラスコンストラクタ
/**
 * 商品オブジェクトを作成
 * @param {string} name 商品名
 * @param {number} price 値段
 * @constructor
 */
function Product(name,price) {

	this.name = name || "無題";
	this.price = price || 0;

};

/**
 * 名前を表示
 */
Product.prototype.displayName = function() {
	
	alert(this.name);
	
};


//子クラスコンストラクタ
/**
 * 本オブジェクトを作成
 * @param {string} name 商品名
 * @param {number} price 値段
 * @param {string} author 著者名
 * @constructor
 * @extends {Product} 
 */
function Book(name, price, author) {
	
	//親クラスのコンストラクタを実行
	this.constructor(name, price);
	
	this.author = author;

};

//Productクラスを継承
Book.prototype = new Product;

/**
 * 名前を表示する
 * @override 
 */
Book.prototype.displayName = function() {
	
	console.log(this.name);
	
	//オーバーライド元のメソッドを呼び出す方法1
	this.superDisplayName= Product.prototype.displayName;
	this.superDisplayName();

	//オーバーライド元のメソッドを呼び出す方法2
	Product.prototype.displayName.apply(this, []);

};


var book1 = new Book("我が輩は猫である", 800, "夏目漱石");
book1.displayName();

多重継承もどき(インターフェースもどき)

//親クラスコンストラクタ
/**
 * 商品オブジェクトを作成
 * @param {string} name 商品名
 * @param {number} price 値段
 * @constructor
 */
function Product(name,price) {

	this.name = name || "無題";
	this.price = price || 0;

};

/**
 * 名前を表示
 */
Product.prototype.displayName = function() {
	
	alert(this.name);
	
};

//インターフェースコンストラクタ
/**
 * @interface
 */
function IMedia(mediaType) {
	
	this.mediaType = mediaType;
	
};

/**
 * メディアタイプを返す
 * @return {string}
 */
IMedia.prototype.getMediaType = function() {};


//子クラスコンストラクタ
/**
 * 書籍オブジェクトを作成
 * @param {string} name 商品名
 * @param {number} price 値段
 * @param {string} author 著者名
 * @constructor
 * @extends {Product}
 * @implements {IMedia}
 */
function Book(name, price, author) {
	
	//親クラスのコンストラクタを実行
	this.constructor(name, price);
	
	//IMediaを多重継承
	this.media = IMedia;
	this.media("paper");
	
	this.author = author;

};

//Productクラスを継承
Book.prototype = new Product;

/**
 * 名前を表示する
 * @override 
 */
Book.prototype.displayName = function() {
	
	console.log(this.name);
	
	//オーバーライド元のメソッドを呼び出す方法1
	this.superDisplayName= Product.prototype.displayName;
	this.superDisplayName();

	//オーバーライド元のメソッドを呼び出す方法2
	Product.prototype.displayName.apply(this, []);

};

//メソッドは継承されないので子クラスで実装
/**
 * メディアタイプを返す
 * @return {string}
 */
Book.prototype.getMediaType = function() {
	
	return this.mediaType;
	
};

var book1 = new Book("我が輩は猫である", 800, "夏目漱石");

book1.displayName();
console.log( book1.getMediaType() );

Flash が HTML5 + SVG + Canvas + JavaScript のオーサリングツールになる日

最近、HTML5 vs Flash みたいな論調があったりしますが、よくよく考えたら HTML5 と対立してるのは Flash ではなく SWFファイルだと気づいた。

WWW は、「どのコンピュータでも、誰でも読めて、誰でも書ける」という基本理念から発生したメディアである。HTMLファイルがプレーンテキストになっているのはそのためだ。なので、バイナリファイルである SWF は「誰でも書けて、誰でも読める」ウェブとはそもそも相容れないものだと僕は思っている。

冒頭でも書いたが、HTML5Flash を駆逐するのではないかというような話が最近でてきているけど、Flash はオーサリングツールであり、駆逐されるとすればそれは SWF ファイルということになる。よくわからないバイナリファイルが消えてくれるのは個人的には大賛成だ。

だけど、SWF が消えたからといって Flash がなくなるとは限らない。逆に Flash は根強く生き続けるんじゃないかと思う。確かに Flash は SWF ファイルを作るためのソフトなんだけど、SWF の代わりに HTML5 + SVG + Canvas + JavaScriptFlash から書き出すことは技術的に不可能じゃないだろう。Flash に慣れ親しんだユーザは沢山いるはずなので、そのような機能が追加されればウェブ標準はもっと広まるだろうし、「誰でも読めて、誰でも書ける」ウェブが実現されるんじゃないかと思う。

オーサリングツールとしての Flash や、言語としとしての ActionScript は個人的にすごい好きなので、Adobe さんには是非とも検討していただきたいところである。

PDF/PPTリンクをGoogle Docs へのリンクへ自動変換するブックマークレットをつくった

@gladdesign さんのつぶやきを受け、PDF/PPTリンクを Goole Docs へのリンクへ自動変換するブックマークレットをつくってみた。

これのブックマークレットとかさくっと作ってくれないかな誰か: ネット上にあるあらゆるPDF/PPTファイルをGoogle Document Viewerで! - IDEA*IDEA http://kuex.us/207b

以下をコピペしてご利用ください。

javascript:(function(){var a=document.getElementsByTagName('a');var g='http://docs.google.com/';var r=new RegExp('^'+g);var l=a.length;for(var i=0;i<l;i++){(function(c){var h=c.href;if(h.match(/.*(pdf|ppt)$/)&&h.match(r)==null){var n=document.createElement('a');n.href=g+"gview?url="+h;n.innerHTML=" <img border='0' src='"+g+"gview/images/goog_logo_bw_1.png' /> ";c.parentNode.insertBefore(n,c.nextSibling);}})(a[i]);}})()

動作確認済み: Safari 4, Firefox 3.5, Chrome 4,IE6, IE7

JavaScript の為のドキュメント作成ツール jsdoc-toolkit

JavaScript用のドキュメント作成ツール jsdoc-toolkit というものを見つけた。
jsdoc-toolkit 自身も JavaScript で記述されているのだが、Rhino を使って動作するため、実際に動かすには Java Runtime 環境が必要。

jsdoc-toolkit を動かす為のシェルスクリプトをつくってみた

jsdoc-toolkit を動かす際は下記のようなコマンドを打つ必要がある。

$ java -jar jsrun.jar app/run.js -a -t=templates/jsdoc  jsのファイル名


でも、いちいち打つのが面倒なのでシェルスクリプトを作ってみた。

#!/bin/bash

#jsdoc-toolkit が設置されているディレクトリのパス
_jsdocDir=~/bin/jsdoc-toolkit


_file=$1  # ドキュメント制作対象の js ファイル名
_out=$2  # ドキュメント出力先ディレクトリのパス

#ディレクトリの指定が無い場合はカレントディレクトリにドキュメントを作成
if [ -z "${_out}" ] ; then
        _out=./
fi


#メイン実行部
java -jar ${_jsdocDir}/jsrun.jar ${_jsdocDir}/app/run.js -a -t=${_jsdocDir}/templates/jsdoc -d=${_out} ${_file}


取り扱いは自己責任で〜

Jslibs を Mac OS X 10.5 にインストールする

Jslibs とは?

Jslibs is a standalone JavaScript development runtime environment for using JavaScript as a general-purpose scripting language.

http://code.google.com/p/jslibs/

まずはソースをとってくる

svn checkout http://jslibs.googlecode.com/svn/trunk/

guname と autoconf213 を ports でインストール

guname と autoconf213 が必要なので、ports経由でインストール。

sudo port install coreutils
sudo port install autoconf213
cd /opt/local/bin
ln -s guname uname
ln -s autoconf213 autoconf2.13

Jslibs を make

make all

なんかコケた

make -C src/jshost all BUILD=opt BITS=32 DEST_DIR=/Users/ynakajima/src/jslibs/trunk/Darwin_32_opt/
make -C ../host/ -f Makefile all
mkdir -p Darwin_opt_32/
gcc -c -Wall -O3 -s -funroll-loops -I../../libs/js/Darwin_opt_32/ -I../../libs/js/src -m32 -fno-exceptions -fno-rtti -felide-constructors -o Darwin_opt_32/host.o host.cpp
In file included from stdafx.h:17,
from host.cpp:15:
../common/platform.h:321:19: error: error.h: No such file or directory
host.cpp:31: warning: ‘_unsafeMode’ initialized and declared ‘extern’
host.cpp: In function ‘void stdErrRouter(JSContext*, const char*, size_t)’:
host.cpp:115: warning: label ‘bad’ defined but not used
host.cpp: In function ‘void* WatchDogThreadProc(void*)’:
host.cpp:238: warning: no return statement in function returning non-void
host.cpp: In function ‘JSBool ExecuteScriptFileName(JSContext*, const char*, bool, int, const char* const*, jsval*)’:
host.cpp:651: warning: ‘status’ may be used uninitialized in this function
../common/errors.h: At global scope:
../common/errors.h:33: warning: ‘JSBool JL_ReportError(JSContext*, J_ErrNum)’ defined but not used
../jslang/../common/jsClass.h:169: warning: ‘JSBool RemoveStatic(JSContext*)’ defined but not used
../jslang/../common/jsClass.h:228: warning: ‘JSBool RemoveClass(JSContext*, JSClass*)’ defined but not used
make[2]: *** [Darwin_opt_32/host.o] Error 1
make[1]: *** [../host/Makefile] Error 2
make: *** [src/jshost] Error 2

調査中。

JavaScript で CSS を切り替える

jsでcssを切り替える方法

function changeStyleSheet(title) {
  var linkElements = document.getElementsByTagName('link');
  for (var i=0,l=linkElements.length; i<l; i++ ) {
    var e = linkElements[i];
    if(e.getAttribute('rel') == 'alternate stylesheet') {
      if(e.getAttribute('title') == title) {
         e.disabled = false;
      } else {
         e.disabled = true;
      }
    }
  }
}

増田美人時計ブックマークレット

美人時計が流行っているみたいなので、増田*1の時刻表示を美人時計に差し替えるブックマークレットを作ってみた。


増田にアクセスしてから、↓をロケーションバーに貼付けて実行すると時刻表示が美人さんになるよ!

javascript:(function(){var j=0;var bt=[];var elms=document.getElementById('body').getElementsByTagName('p');for(var i in elms) {if(elms[i].className=='sectionfooter'){bt.push(elms[i]);}};function tm() {if(j<bt.length){bt[j].innerHTML=bt[j].innerHTML.replace(/(\d.):(\d.)/,'<img style=\'width:200px\'  src=\'http://www.bijint.com/jp/img/photo/$1$2.jpg\'  />');j++;}};var k=setInterval(tm,1500)})();

一応、setInterval で1.5秒毎に1画像づつ差し替えてます。

動作確認済み: Firefox 3, Safari 4, Opera 9, IE7, IE6

*1:2ch用も作ってみたけど、自粛しました。