javaScript

2011年4月 8日 (金)

javaScript 再帰関数2

Haskellおもしろい。

そしてmap関数。

まー、配列は引数で受け取らず、処理をArray.prototypeのメソッドにしちゃって、this
で受け取るほうが良いのかな?


//a -> [a] -> [a]
function con( v, ary ) {
return [v].concat(ary);
}


//配列の要素それぞれに関数を適用し、新しい配列を返す
//(a -> b) -> [a] -> [b]
function map( f, ary ) {
if( ary.length == 0 ) {
return [];
}else {
var v = ary.shift();

return con( f(v), map(f, ary) );
}
}

var a = [3,2,5,20,4,2];

console.log( map( function( n ){ return n * 2; }, a.slice(0) ) ); //[6,4,10,40,8,4]

| | コメント (0) | トラックバック (0)

JavaScript 再帰関数

最近Haskellをみてて、こんなことできるんだ、と思ったんで、再帰処理をjavaScriptでかいた。

ポイントは、forとか、foreachのループなしで再帰でやってることです。
//a -> [a]とかは、Haskellのおまじないです。

//準備開始

//a -> [a] -> [a]
function con( v, ary ) {
return [v].concat(ary);
}

//a -> [a] -> [a]
function con2( ary, v ) {
return ary.push(v);
}


//(Ord a) => a -> a -> Bool
function max(a, b) {
return (a > b) ? a : b;
}

//準備終了

//最大値取得
//(Ord a) => [a] -> a
function getMaximum( ary ) {

if( !ary ) {
throw "error bad param.";
}

if( ary.length == 0 ) {
throw "error empty.";
}
else if( ary.length == 1 ) {
return ary[0];
}
else {
var x = ary.shift();

//再帰呼出し
return max( x, getMaximum( ary ) );
}
}

//値を指定個数繰り返し配列に
//Int -> a -> [a]
function replicate( n, v ) {
if( n <= 0 ) {
return [];
}else {

//再帰呼出
return con(v, replicate( n-1, v ));
}
}

//配列の要素を先頭から取得
//(Num n, Ord n) => n -> [a] -> [a]
function take( n, ary ) {
if( n <= 0 ) {
return [];
}else if( ary.length == 0 ) {
return [];
}else {
var v = ary.shift();

//再帰呼出
return con( v, take( n-1, ary ) );
}
}

//配列の要素を逆転
//[a] -> [a]
function reverse( ary ) {
if( ary.length == 0 ) {
return [];
}else {
var v = ary.shift();

//再帰呼出
return reverse( ary ).concat( [v] );
}

}

//2つの配列の要素をまとめて配列の要素に
//[a] -> [b] -> [(a,b)]
function zip ( ary1, ary2 ) {

if( ary1.length == 0 ) {
return [];
}else if ( ary2.length == 0 ) {
return [];
}else {
var v1 = ary1.shift();
var v2 = ary2.shift();
var v = [v1,v2];
return con( v, zip( ary1, ary2 ) );
}
}

//配列に値が存在するか
//(Eq a) => a -> [a] -> Bool
function elem( v, ary ) {

if( ary.length == 0 ) {
return false;
}else {
var x = ary.shift();

if( v == x ) {
return true;
}else {
return elem( v, ary );
}
}
}

//テスト開始

var a = [3,2,5,20,4,2];
var b = [1,2,3,4];

//a.slice(0)は、配列の複製です。参照渡しでaの中身が変わらないようにしてます。

console.log( getMaximum( a.slice(0) ) ); //20

console.log( replicate( 3, 5 ) ); //[5,5,5]

console.log( take( 2, a.slice(0) ) ); //[3,2]

console.log( reverse( a.slice(0) ) ); //[2,4,20,5,2,3]

console.log( zip( a.slice(0), b.slice(0) ) ); //[[3,1],[2,2],[5,3],[20,4]]

console.log( elem( 5, a.slice(0) ) ); //true
console.log( elem( 999, a.slice(0) ) ); //false

| | コメント (0) | トラックバック (0)

2011年3月 9日 (水)

javaScript jQueryを読む

/*
jqueryを読む。
バージョンは、1.5.1を使っております。

とりあえず、大枠はこんな感じ。
特別な意味をなくすため、変数名を「jQuery」ではなく、「o1」などとしています。
*/



(function( w, undefined ) {
var o1 = (function () {
var o2 = function( selector,context ) { console.log('gaga'); };

return o2;
})();
w.o3 = w.$ = o1;
})(window);

o3(); //gaga
console.log(o3 === $); //true
$(); //gaga



//////////////////////////////////////

まず、即時実行関数として大ソトの構造
(function( w, undefined ) {
})(window);
これは、定義した関数を、グローバルオブジェクトwindowを引数にしてすぐに実行しています。

次に、
var o1 = ...
の部分ですが、これも即時実行関数で、返却されたo2がo1に入ります。
o1は、グローバルオブジェクトの$とo3に代入されます。
これによって、大ソトの構造外でもこれらの変数が利用可能になります。
o3も$も、実態はo2に代入された関数です。

macだと対応する括弧に移動できるエディタが見当たらないです。
知ってる人が入れば教えてください。Eclipse?

| | コメント (0) | トラックバック (0)

javaScript prototypeは関数オブジェクトに自動でできるプロパティ(型はオブジェクト)

javaScriptは、下記のような練習をして慣れていくしかないなー。


function F() {}
F.prototype.name = 'gabi';

var x1 = new F();

var o1 = F.prototype; //退避

var o2 = { name: 'taro' };
F.prototype = o2; //上書き

var x2 = new F();

console.log(o1.name); //gabi 元のプロトタイプは生きている
console.log(x1.name); //gabi x1は、元のプロトタイプを見ている
console.log(x2.name); //taro x2は、上書きされたプロトタイプを見ている

| | コメント (0) | トラックバック (0)

2011年3月 7日 (月)

javaScript []によるプロパティへのアクセス

javaScriptで、オブジェクトのプロパティにアクセスするときに、o.nameの形式とは別に、
o['name']という形式があります。これを使うと、文字型の変数を使ってプロパティに
アクセスできます。

動的な操作を行うときによく使われる模様です。

//関数の定義
function Test() {}

//配列の定義
var ary = ['a','b','c','d'];

for(var i = 0; i < ary.length; i++) {
var element = ary[i];

//Testオブジェクトが、elementプロパティを持っていなければ
if(typeof Test[element] !== 'object') {

//elementプロパティを設定
Test[element] = {
name: element + element + element
};
}
}

//Testオブジェクトに、aプロパティができた
console.log(Test.a.name); //aaa

| | コメント (0) | トラックバック (0)

2011年3月 2日 (水)

javaScript constructorプロパティ

//constructerプロパティを持つものは何か

function F() { this.name = 'taro'; }

var o = new F();

//何がconstructerプロパティを持っているのか

console.log(a.constructor); //function Object() ...
console.log(F.constructor); //function Function() ...
console.log(F.prototype.constructor); //function F() {this.name='taro';}
console.log(o.constructor); //function F() {this.name='taro';}

//全部持ってるんですね。

//プリミティブ型は持ってないはず

var i = 0;
var s = 'a';
var u; //undefined

console.log(i.constructor); //function Number() ...
console.log(s.constructor); //function String() ...
//console.log(u.constructor); //ERROR

//あれ、i,sも持ってることになってる。
//プロパティにアクセスしたことで、一時的にNumber,Stringオブジェクトに
//型変換されたんでしょう

//constructerプロパティは、関数オブジェクトなので、
//それを使って新しいオブジェクトを作れるはずです。

var o2 = new F.prototype.constructor();

console.log(o2.name); //taro

//作れました。

//下の2つは同じオブジェクト?
console.log(F.prototype.constructor == o.constructor); //true
console.log(a.constructor == b.constructor); //true

//同じでした。

//自前で持ってる?
console.log(F.prototype.hasOwnProperty('constructor')); //true
console.log(o.hasOwnProperty('constructor')); //false
console.log(a.hasOwnProperty('constructor')); //false

//インスタンスのconstructorは、プロトタイプチェーンで与えられるようです。

//constructorは、代入可能なので、上書きして破壊してみます。
function F2(){ this.name = 'jiro';}
F2.prototype.constructor = 100;
var o3 = new F2();
console.log(o3.name); //jiro
console.log(o3.constructor); //100

//継承の実験

function Parent() {this.name = 'saburo';}
function Child() {}

Child.prototype = new Parent();

var child = new Child();
console.log(child.name); //saburo
console.log(child.constructor); //function Parent() ...

//prototypeの代入による継承は、constructorが変になるみたい。
//(newしたのはChildなのに、constructorは、Parentになってる)

| | コメント (0) | トラックバック (0)

javaScript 関数オブジェクト prototype

prototypeプロパティは、
 全てのオブジェクトにつく
ではなく、
 全ての関数オブジェクトにつく
ということらしい。

関数オブジェクトは、newの対象となって、オブジェクト生成を行えるオブジェクトで、
その生成によって生じたオブジェクトが、prototypeプロパティのオブジェクトを
参照している。(生成された(非関数)オブジェクトはprototypeプロパティを持たない)

ということでOKでしょうか?

var o1 = {my_name:'taro'};

function FFF() {}

var f = function() {};

console.log(typeof o1.prototype); //undefined
console.log(typeof FFF.prototype); //object
console.log(typeof f.prototype); //object


FFF.prototype = o1;

var fff = new FFF();

console.log(typeof fff.prototype); //undefined
console.log(typeof FFF.my_name); //undefined
console.log(typeof fff.my_name); //string

| | コメント (0) | トラックバック (0)

2011年3月 1日 (火)

javasScript 関数とtypeof

typeofでいろいろやってみた。

var o = {};
console.log(typeof o);

var f = function () {};
console.log(typeof f);

function f2 () {};
console.log(typeof f2);

f2 = 'aaa';
console.log(typeof f2);

var f3 = function fsan () {
console.log(typeof fsan);
};
console.log(typeof fsan);

f3();

答え:
object,function,function,string,undefined,function

f2の上書きができてしまうあたりが危険です。

| | コメント (0) | トラックバック (0)

javaScript 関数の代入

javaScriptの式を見るときに、よく似ていて意味が違うのが、

var a = function () { ... };

var b = function () { ... } ();
です。

aは右辺で生成された関数オブジェクトが代入されましたが、
bは、右辺の関数オブジェクトが実施された結果が代入されています。

何が代入されたかはreturn文によって決まります。

よって、
var c= function ...という記述を見かけた場合、そのケツにカッコがあるかどうかを追いかけ、
ある場合は、returnしている要素を凝視します。

以下の3つの違いがわかりますか?


var o = function () {
var name = 'taro';
function sayHello(){
console.log('Hello ' + name);
}
sayHello();
};

o();

var o2 = function () {

var name = 'jiro';
return function () {
console.log('Hello ' + name);
}
}();

o2();

var o3 = function () {
var name = 'saburo';
return {
sayHello: function () {
console.log('Hello ' + name);
}
}
}();

o3.sayHello();

結果: Hello taro, Hello jiro, Hello saburo

| | コメント (0) | トラックバック (0)

2011年2月26日 (土)

javaScript 関数の宣言、関数オブジェクトの作成、関数の実施

javaScriptは、関数に

関数宣言
function aaa(){ alert('aaa'); }

と関数式
var o = functioin bbb(){ alert('aaa'); };
があり、

関数を実施する。
aaa();
o();

また、即時に実施する関数式もある。
var o2 = function ccc(){ return 1+1; }();

これらが、「宣言」「生成」なのか、「実施」なのかを分けるところから、
javaScriptのリーディングは始まる。

下記scriptの実施結果のコンソール出力の予想がつきますか?

console.log('no1')

//関数f1の宣言
function f1()
{
console.log('f1');
}

console.log('no2');


//f1の実施
f1();

console.log('no3');


//関数オブジェクトoの作成
var o = function f2(){
console.log('f2');
};

console.log('no4');

//oの実施
o();

console.log('no5');

//f3の宣言
function f3(){

console.log('f3');

return function f4(){
console.log('f4');
}
}

var o2 = f3();

console.log('no6');

//o2の実施
o2();

答えは、
 no1,no2,f1,no3,no4,f2,no5,f3,no6,f4
です。

| | コメント (0) | トラックバック (0)

その他のカテゴリー

Haskell | iphone アプリ | iphone開発 | javaScript | Kindle | カメラ | 書籍