94_111122114208_1

JS入門の基礎

JSを書く手順

  1. まずレイアウトを実装する
  2. 実現原理を考える
  3. JSの構文を理解する

特定の要素を削除したい場合の実装

  • display: none; 表示を無しにする
  • visibility: hidden; 非表示にする
  • width \ height
  • 透明度
  • left \ top
  • 背景色と同じdivでその要素を覆う
  • margin値を利用する
  • ……

要素の取得

  • getElementById() ——静的メソッド。前にはdocumentのみ付けることができる
  • document.body、document.title ページ内に1つしかない要素
  • getElementsByTagName() ——動的メソッド。前にはdocumentだけでなく他の要素も付けることができる。配列に似た要素の集合を返す
    • 配列に似たlengthを持つ
    • 配列に似た使い方ができる。例えば ali
    • TagNameを使うときは、必ず角括弧[]を付ける必要がある
    • いわゆる動的メソッドとは、jsで動的に追加した要素も、getElementsByTagName()なら見つけられるが、document.getElementByIdでは見つけられないことを指す

イベント

イベント:マウスイベント、キーボードイベント、システムイベント、フォームイベント、カスタムイベント
  • onclick
  • onmouseover
  • onmousedown
  • onmouseout
  • onmouseup
  • onmousemove
  • ……

イベントの追加方法

  • 要素.onmouseover

関数

関数はコマンドのようなもので、何かを行うもの。例: function abc() { // 決して自動実行されない! … }
  1. 直接呼び出し:abc();
  2. イベント呼び出し:要素.イベント = 関数名 (oDiv.onclick = abc;)
  3. ……
function(){} 匿名関数 要素.イベント = function(){}

テスト

  • alert(1); OKボタン付きの警告ボックス;alert('ok'); 'ok' は文字列
  • 初心者:常に書いたらすぐテストする習慣をつけるのが良い

変数

  • var li = document.getElementById('lis');
  • var num = 123;
  • var name = 'leo';

JSの属性操作

HTML属性の操作

  • 属性名
  • 属性値
  • 属性の読み取り操作:取得、検索
    • 要素.属性名
  • 属性の書き込み操作:置き換え、変更
    • 要素.属性名 = 新しい値
    • 追加したい場合は、+= を使う必要がある
  • innerHTML は要素内のすべてのHTMLコードを読み取る
文字列連結:プラス記号

属性の読み書き操作の注意点

  • JSのプロパティには「-」を使用できない。例えば font-size は fontSize に変更する
  • class はJSでは予約語である。JSでclassを使用する場合は className を使う
  • すべての相対パスを判定に使ってはいけない(例:imgのsrc、またhref)
  • 色の値は判定に使わないこと(red、#f00、rgb(250, 0, 0)などの書き方があるため)
  • 相対パスも判定に使わないこと
  • innerHTMLの値を判定に使わないこと
  • IE6、IE7、IE8ではフォーム要素のtypeは変更できない。サポートされておらず、エラーが発生する。その他はすべて可能。
  • 一部のブラウザでは、float値を直接変更することはサポートされていない場合がある。JSでは、IE(styleFloat)と非IE(cssFloat)で区別して対応できる。
  • 判定に使えないものは、スイッチを作成し、ブール値を利用して実現できる
互換性について:
  • 技術面:互換性を習得できる必要がある(互換性問題の解決策)
  • 要件面:相談して進める(最も正確な表示案を提供する)

[](角括弧)の使用

  • ドット「.」の後の値は変更できない
  • 角括弧[]の中の値は変更できる。JSでは「.」を「[]」に置き換えることが許可されている

条件判断

  • if(条件){……};
  • if(条件){……} else {……};
  • if(条件1){……} else if(条件2) {……} else if(条件3) {……} else {……};

配列

  • 「データを格納する倉庫」
  • 角括弧[]を使用し、半角カンマで区切る。最後のデータの後にはカンマを付けない
  • 配列のlengthプロパティ
  • 配列の最後に要素を追加するには push() を使う

forの応用

forループの使用シーン:
  • 特定のコードを繰り返し実行したい場合
  • 実行するたびに、数字が変化する場合
forループの実行順序:1→234→234……
  1. var i = 0;
  2. i < 3; 重要なステップ
  3. 括弧内のすべてのコード
  4. i++
次のようなループに注意:
for (var i=0; i<aLi.length; i++) {
  aLi[i].onclick = function(){
    alert(i);
  }
}
上記のコードでは0、1、2ではなく3が一度だけポップアップ表示される。ここで注意すべきは、forループ内に関数を含み、その関数内でiを使用する場合、スコープの関係により、iは想像通りに逐次増加しないということである。

cssTextテキストフォーマットと属性操作

  • oDiv.style.cssText = 'width: 200px; height: 200px;';
  • cssTextはhead内のstyleの設定には影響しない。ただし、インラインスタイルは変更される(注意:インラインスタイルを追加するのではなく、置き換えることになる)

ボタンクリック後、機能を繰り返さないための考え方

  1. ボタンに制限をかける。例えば、一度クリックした後、oBtn.disabled = true; を設定する
  2. さらにボタンに制限をかける。例えば、一度クリックした後、ボタンを非表示にする oBtn.style.display = 'none';
  3. ボタンが追加したものをクリアし、再度追加する。先にクリアしてから生成する
  4. 判定を使用する

thisの指す先とthisの応用

window はJSの中の「ボス」である
function fn1(){
    alert(this);
}
fn1();
上記のコードで関数fn1()を実行することは window.fn1(); と同等である。したがって、関数体内でポップアップ表示される this は依然として window である。
function fn1(){
    alert(this);
}
oBtn.onclick = fn1;
上記のボタンのクリックイベントで呼び出されるfn1関数では、最終的にポップアップ表示されるのはこのボタンであり、windowではない。
function fn1(){
    alert(this);
}
oBtn.onclick = function(){
    alert(this)
}
上記のコードでは、ボタンをクリックしてポップアップ表示される this は依然として oBtn というボタンである。
function fn1(){
    alert(this);
}
oBtn.onclick = function(){
    fn1();
}
上記のコードでは、oBtnボタンをクリックすると、ポップアップ表示されるのは oBtn というオブジェクトではなく、window である。
<input id="btn2" type="button" value="按钮2" onclick="alert(this)" />
上記のコードはインラインイベントであり、ポップアップ表示される this はこのボタン btn2 である。
function fn1(){
    alert(this);
}
<input id="btn2" type="button" onclick="fn1();" value="按钮2” />
上記のコードでは、ポップアップ表示される this は window である。
  • this: 現在のメソッド(関数)を呼び出しているそのオブジェクト
function fn1(){
    this
}

fn1(); this => window

oDiv.onclick = fn1; this => oDiv

oDiv.onclick = function(){
    this => oDiv
};

oDiv.onclick = function(){
    fn1(); fn1()里面的this => window
}

<div onclick="  this  "></div> this => div

<div onclick = "  fn1();  "></div>  fn1()里面的this => window
<script>

fn1(this);
function fn1(obj){
  obj => window
}

oDiv.onclick = function(){
  this
  fn1(this);
};
function fn1(obj){ obj => oDiv }

</script>
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />

window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  for(var i=0; i<aBtn.length; i++) {
    aBtn[i].onclick = function(){
      this.style.background = 'yellow';
    }
  }
}
上記のコードの動作は以下のコードの動作と同等である。thatの使用方法に注意すること。
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />

window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  var that = null; 
  
  for(var i=0; i<aBtn.length; i++) {
    aBtn[i].onclick = function(){
      that = this;
      fn1();
    };
  }
  function fn1(){
    //this => window
    that.style.background = 'yellow';
  }
}
上記のコードはさらに以下のコードとも同等である:
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />

window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  
  for(var i=0; i<a.aBtn.length; i++) {
    aBtn[i].onclick = fn1; //注意不要在fn1后面加括号
  }
  
  function fn1(){
    this.style.background = 'yellow';
  }
}

カスタム属性、インデックス値

カスタム属性の読み書き操作

window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  
  aBtn[0].abc = 123; //自定义属性
  
  // alert(aBtn[0].abc); 自定义属性的读
  // aBtn[0].abc = 456; 自定义属性的写
}
JSは任意のHTML要素に任意の数のカスタム属性を追加できる

カスタム属性の応用

カスタム属性を使用すると、要素にスイッチ属性を追加して、制御スイッチとして使用できる。次の例のとおりである:
window.onload = function(){
  var aLi = document.getElementsByTagName('li');
  // var onOff = true; 一个onOff只能控制一个开关。要为多个元素设置各自的开关,就要给每个元素加个onOff开关。
  
  for(var i=0; i<aLi.length; i++) {
    aLi[i].onOff = true;
    aLi[i].onclick = function(){
      if (this.onOff){
        this.style.background = 'url(img/active.png)';
        this.onOff = false;
      } else {
        this.style.background = 'url(img/normal.png)';
        this.onOff = true;
      }
    }
  }
}

自身の増加する数値の取得と配列内容のマッチング

ウェブページに3つのボタンを設置し、デフォルト値を0とする。ボタンをクリックするたびに、文字がABCDの順に順番に切り替わる。
<input type="button" value="0" />
<input type="button" value="0" />
<input type="button" value="0" />
  var aBtn = document.getElementsByTagName('input');
  var arr = ['A', 'B', 'C', 'D'];
  
  for(var i=0; i<aBtn.length; i++){
    aBtn[i].num = 0;
    aBtn[i].onclick = function(){
      this.value = arr[this.num]
      this.num++;
      if(this.num === arr.length){
        this.num = 0;
      };
    };
  };

インデックス値の追加、配列・HTML要素のマッチング

3つのボタンのvalueと配列内の値を順にマッチングさせる。
<input type="button" value="btn1" />
<input type="button" value="btn2" />
<input type="button" value="btn3" />
window.onload = function(){
  var aBtn = document.getElementsByTagName('input');
  var arr = ['莫涛','张森','杜鹏'];
  
  for(var i=0; i<aBtn.length; i++){
    aBtn[i].index = i; //自定义属性index,添加索引值
    aBtn[i].onclick = function(){
      //alert(i); //不会弹出1、2,直接弹出3,也就是aBtn的长度。也就是说,在基础阶段,在for循环所包的函数里面再用i是不靠谱的。
      this.value = arr[this.index];
    };
  };
}
上記はインデックス値で配列の値をマッチングさせる方法である。HTML内の要素をマッチングさせる場合も同様である。 「マッチング」「対応」の関係を構築したい場合は、インデックス値を使用する。

データ型、型変換

ECMAScript:標準、核心

データ型

  • HTMLタグの種類:
    • block
    • inline
    • inline-block
    • table
    • ……
  • JSにおけるデータ型:
    • 数値(NaNは数値型に属する)
    • 文字列
    • ブール値
    • 関数型
    • オブジェクト
      • obj
      • []
      • {}
      • null(空にはカスタム属性を追加できない)
    • 未定義(undefined)
typeofはデータ型を判定するために使用する。 文字列メソッド charAt():文字列のインデックス(添字)を使用して部分文字列を取得する。 オブジェクトにはカスタム属性を追加できる。関数をオブジェクトに渡した場合、そのオブジェクトにメソッドを追加したことになる。

JSのデータ型変換

文字列を数値に変換する方法:

JSメソッド:Number();

var a = '100';
alert(a + 100); //'100100'

var b = '00100';
alert(Number(b)); //100

var c = '+100';
alert(Number(c)); //100

var d = '';
alert(Number(d)); //0

var e = '   ';
alert(Number(e)); //0

var f = true;
alert(Number(f)); //1

var g = false;
alert(Number(g)); //0

var i = [];
alert(Number(i)); //0 空数组用Number转出来是0

var j = [''];
alert(Number(j)); //0

var k = [123];
alert(Number(k)); //123

var l = ['123'];
alert(Number(l)); //123

var o = null;
alert(Number(o)); //0

----------------------------
var m = [1,2,3];
alert(Number(m)); //NaN

var json = {abc:123};
alert(Number(json)); //NaN

var json2 = {};
alert(Number(json2)); //NaN 即使是空json,Number方法也转不了

var h = function(){};
alert(Number(h)); //NaN

var p;
alert(Number(p)); //undefined 

var q = '100px';
alert(Number(q)); // NaN

parseIntとparseFloat

var a = '100px';
alert(parseInt(a)); //100

var b = '100px123456789';
alert(parseInt(b)); //100

var d = '-100px';
alert(parseInt(d)); //-100 parseInt还是认加减号的

var e = '   100px';
alert(parseInt(e)); //100 parseInt也是认空格的

var f = '000000100px';
alert(parseInt(f)); //100

var g = '12.34元';
alert(parseInt(g)); //12 parseInt只能转出整数
------------------------------
var c = true;
alert(parseInt(c)); //NaN

//parseInt也不能用于转函数等

parseInt()メソッドにはもう1つのパラメータがあり、それは何進数で変換するかを指定するものである。例えば parseInt(a, 10); は10進数で変換することを示し、parseInt(b, 2); は2進数で変換することを示す。
var a = '12.34元';
alert(parseFloat(a)); //12.34

var b = '12.3.4元';
alert(parseFloat(b)); //12.3 parseFloat只认第一个小数点
parseInt と parseFloat の併用これにより、特定の値が整数か小数かを判定できる。次のとおりである:
var num = '200.345';
if(parseInt(num) == parseFloat(num)) {
  alert(num + '是整数');
} else {
  alert(num + '是小数');
}

JSにおける不思議な暗黙の型変換

明示的な型変換(強制型変換):
  • Number();
  • parseInt();
  • parseFloat();
暗黙の型変換:
  • - * \/ \% 減算、乗算、除算、剰余は文字列を数値に変換できる
  • + プラス記号は数値を文字列に変換できる
  • ++ -- インクリメント、デクリメント演算子は文字列を数値に変換できる
  • < > 大なり記号、小なり記号は文字列を数値に変換できる。数値の比較を行うのか文字列の比較を行うのかに必ず注意すること
  • ! 否定は右側のデータ型をブール値に変換する
  • ==
alert('200' - 3); //197
alert(200 + '3'); //2003

var a = '10';
a++;
alert(a); //11

alert('10'>9); //true
alert('1000000'>'9'); //false
//注意:数字的比较和字符串的比较不同;字符串的比较是一位一位的比较。

alert(!'ok'); //false
alert(!100); //false

alert('2' == 2); //true
alert('2' === 2); //false 三个等号不仅判断值,还会先判断两者的类型
暗黙の型変換で変換できない場合もNaNが返される。例えば alert('……' - 9); はNaNをポップアップ表示する。

isNaNの応用実例

NaN: (not a number)。NaNは数字ではない数値型である。すべての数値は数値型であるが、すべての数値型が数値であるとは限らない。
  • NaNは数値型であるが、数字ではない。
  • プログラム内にNaNが出現した場合、それは必ず不正な演算操作が行われたことを示している。
  • NaNはfalseである。
  • NaNは自分自身とも等しくない。
var a = Number('abc');
//alert(a); //NaN
//alert(typeof(a)); //number

if(a) { //会弹出‘假’,说明NaN是false
  alert('真');
} else {
  alert('假');
}

//alert(a === a); //false NaN比较,比出false
isNaN:is not a Number は「数字ではないかどうか」(数字ではない)という意味である。 isNaN(); はメソッドであり、処理を行うために使用する。
  • 特定の値が数字かどうかを判定するのに役立つ。
  • 数字を好まない、数字を嫌う(数値型を嫌うわけではない。isNaNはNaNに出会うと非常に喜び、trueを返す。しかしNaNは数値型である)。数字を判定するために使用する。例:alert(isNaN(2)); はfalseを返す。alert(isNaN('我爱你')); はtrueを返す。alert(isNaN(function(){})); はtrueを返す。
isNaNの判定プロセスは、括弧内のものをNumberに渡し、Numberが数値に変換できればfalseを返し、変換できなければtrueを返す。
alert(isNaN('250'));
//Number() '250' => 250 => false

alert(isNaN(true));
//Number() true => 1 => false

alert(isNaN([]));
//Number() [] => 0 => false
以下はisNaNの簡単な応用例である:
<input type="text" />
<input type="button" value="判断输入值是不是数字" />
window.onload = function(){
  var aInp = document.getElementsByTagName('input');
  var str = '';
  
  aInp[1].onclick = function(){
    str = aInp[0].value
    //alert(type of str); //总是返回string 从HTML中拿到的内容,类型都是字符串
    
    if(isNaN(str)){
      alert(str + '不是数字');
    } else {
      alert(str + '是数字');
    }
  }
}

関数への引数渡し

引数 = JSのデータ型:
  • 数値
  • 文字列
  • ブール値
  • 関数
  • オブジェクト
  • 未定義

引数の型判断

fn1(100);
fn1('miaov');
fn1(function(){alert(1);});

function fn1(a){
  if(typeof a === 'number' &amp;&amp; a === a) {
    alert(a+20);
  } else if (typeof a === 'string'){
    alert(a.charAt(2));
  } else if (typeof a === 'function'){
    a();
  }
}

コード再利用の手順

  1. HTMLコードの構造をできるだけ統一させる。親要素から子要素を選択できるようにする
  2. 核心となるメインプログラムを実装し、関数で包む
  3. 各グループで異なる値を見つけ出し、引数渡しで実現する

JSスコープ

スコープとは何か
  • 域:空間、範囲、領域
  • 作用:読み取り、書き込み

ブラウザの「JSパーサー」

"JSパーサー":ブラウザ内でJSを読み取るための専用プログラム。少なくとも次の2つのことを行います(もちろん他にもあります):
  1. 準備作業(「何かを探す」):var、function、引数に基づいてものを探す——JSの事前解析(プリパース)a = 未定義(undefined) すべての変数は、コードを正式に実行する前に、事前に値が代入されています:未定義。 fn1 = function fn1(){alert(2);} すべての関数は、コードを正式に実行する前に、関数ブロック全体です。 同名のものが出てきたら、1つだけ残す。
  2. コードを1行ずつ解釈する。1行読むごとに、事前解析したライブラリの中を確認しに行く。式(= + - * / % ++ – ! 引数……が付いているものはすべて式。値を変更できるのは式)に出会うと、ライブラリの中の値を変更しに行く。
alert(a); //未定义
var a=1; //在库里面a的值由未定义换成1
function fn1(){alert(2);}
alert(a); //弹出:function a(){alert(4);}
var a=1; //预解析中的a改为了1
alert(a);  //弹出1
function a(){alert(2);}//函数声明,没有改变a的值。什么也没发生。
alert(a); //继续弹出1,因为a在预处理库里面的值没有被改过。
var a=3; //预处理中a的值变为3
alert(a); //弹出3
function a(){alert(4);} //函数声明,什么也没有发生
alert(a); //继续弹出3
a(); //报错 a is not a function
上記のコードの事前解析でのプロセスは次のとおりです: 1)事前解析: var function 引数 …… var a = 1 を読む => a は未定義 function a(){alert(2);} を読む => a = function a(){alert(2);} 変数と関数が同名になった場合は、関数だけを残す: a = function(){alert(2);} var a = 3 を読む => a は未定義。ここでは上記の名前がaの関数と同名なので、やはり a = function(){alert(2);} を保持する。 function a(){alert(4);} を読む => a = function a(){alert(4);} 先ほどの a = function(){alert(2);} と同名になり、文脈から、後の関数が前の関数を上書きする。したがって、事前解析では a = function(){alert(4);} だけが残る。 2)1行ずつコードを解釈する。式を読むと、式は事前解析の値を変更できる。引数も事前解析の値を変更できる。関数呼び出しに遭遇すると、また2つのことを行う:事前解析、1行ずつのコード解析。関数宣言は式ではないので、事前解析内の値を変更しない。

スコープ

  • <script>タグ内で宣言された関数と変数は、すべてグローバル関数およびグローバル変数です(ただし、JSパーサーは1つのブロックを処理し終えてから、別のブロックを処理します)。上から下へ
  • 関数:関数も1つのスコープであり、やはり「先に探してから実行」します。内側から外側へ
  • オブジェクト {}
スコープチェーン:子スコープから親スコープへジャンプするプロセス
<script>
alert(a); //报错:a is not defined。因为在预解析里面压根就没有a这个东西
</script>

...

<script>
var a = 1;
</script>
<script>
alert(a); //不报错,会弹出undefined。因为预解析里面有a这个东西,但是由于执行的时候,还没有改变a的值,因此a的值为undefined
var a = 1;
</script>

...

<script>
</script>
<script>
var a = 1; //预解析里面存了a,并且a的值存为1
</script>

...

<script>
alert(a); //弹出1
</script>
var a = 1; //预处理中的全局变量a的值改为1
function fn1(){
    alert(a);
    var a = 2;
} //函数声明,什么也不做
fn1(); //遇到函数调用,开始进行预解析和逐行解读代码。在函数内,先预解析出一个局部的 a 是未定义(局部的a与全局的a一点关系都没有);然后读代码,alert(a)弹出的是undefined;然后继续执行,遇到表达式,将局部的变量a的值改为2。这时fn1的函数执行已经完成了。
alert(a); //弹出全局变量a为1
上記のコードのJSパーサーでのシミュレーションは次のとおりです: 1)事前解析 var function 引数…… a = … fn1 = function fn1(){ alert(a); var a=2; } 2) 1行ずつコードを解析する もう1つのコード:
var a = 1; //预处理中的全局变量a的值改为1
function fn1(){
    alert(a);
    a = 2;
} //函数声明,什么也不做
fn1(); //遇到函数调用,开始进行预解析和逐行解读代码。在函数内,没有任何函数和变量声明,因此预解析里面没东西;然后读代码,alert(a),在局部没有找到预解析的a,于是从子级作用域跳到父级作用域去找,找到了全局的a,所以弹出的是全局变量a的值1;然后继续执行,遇到表达式,将全局变量a的值改为2。这时fn1的函数执行已经完成了。
alert(a); //弹出全局变量a为2
var a = 1; //预处理中的全局变量a的值改为1
function fn1(a){ //参数本质上就是一个局部变量
    alert(a);
    a = 2;
} //函数声明,什么也不做
fn1(); //遇到函数调用,开始进行预解析和逐行解读代码。在函数内,找到参数a,因此预处理里面有个局部的a是未定义。;然后读代码,alert(a),弹出的是局部的a为undefined;然后继续执行,遇到表达式,将局部变量a的值改为2。这时fn1的函数执行已经完成了。
alert(a); //弹出全局变量a为1
var a = 1; //预处理中的全局变量a的值改为1
function fn1(a){ //参数本质上就是一个局部变量
    alert(a);
    a = 2;
} //函数声明,什么也不做
fn1(a); //遇到函数调用,开始进行预解析和逐行解读代码。在函数内,找到局部参数a,因此预处理里面有个局部的a是未定义。;然后读代码,读到第一行function fn1(a),这时有参数进来,把全局的a的值1赋给了局部变量a,这时局部变量a的值变为1,alert(a),弹出的是局部的a为1;然后继续执行,遇到表达式,将局部变量a的值改为2。这时fn1的函数执行已经完成了。
alert(a); //弹出全局变量a为1

関数内の値を取得したい場合

  • 方法1、グローバル変数を関数の中で使う。関数はグローバル変数を読み書きできるからです。次のコードを参照してください:
var str = '';
function fn1(){
    var a = '大鸡腿~';
    str = a;
}
fn1();
  • 方法2、関数の中でグローバル関数を呼び出し、引数を渡すことで実現します。次のコードを参照してください:
function fn2(){
    var a = '99999999克拉钻石';
    fn3(a);
}
fn2();
function fn3(a){ //注意这个a是fn3里面的,与fn2里面的a毫无关系
    alert(a);
}
注意事項関数の中括弧{}はスコープです。if(){}はスコープではありません。for(){}もスコープではありません。スコープだけが事前解析されてから実行されます。ifやforの中括弧{}には事前解析のプロセスがありません。
alert(a); //弹出undefined。这说明if大括号中的a已经在全局就被预解析了,因此if的大括号并不是作用域
if(true){
    var a=1;
}
ただし、注意が必要です:
alert(fn1); //在火狐浏览器里面会报错说fn1 is not defined。但是在chrome浏览器里可以正常弹出fun1函数。

if(true){
    var a = 1;
    function fn1(){
        alert(123);
    }
}
Firefoxの事前解析だけは、ifやforの括弧で囲まれた関数を事前解析できません。そのため、互換性の問題があります。したがって、グローバル関数やグローバル変数を定義したい場合は、ifやforの中括弧{}の中にはできるだけ入れずに、中括弧{}の外に置くようにしてください。
for(var i=0; i<aBtn.length; i++){
    aBtn[i].onclick = function(){
        alert(i); //弹出3。因为必须for循环全部执行完成之后,aBtn才能够点击。但是for循环执行完了,外面的i已经变成3;但是在function里面又没有i,自然找到了外面的i,也就是3.
    }
}
for(var i=0; i<aBtn.length; i++){
    aBtn[i].onclick = function(){
        alert(i); //这时候弹出的就不是3了,是undefined
        
        for(var i=0; i<aBtn.legnth; i++){
            aBtn[i].style.background = 'yellow';
        }
    }
}
for(var i=0; i<aBtn.length; i++){
    aBtn[i].onclick = function(){
        alert(i); //下面for循环的括号中的var删去了,function里面又找不到i了,所以到父级找到了i,又是个3。因此,此处会弹出3。
        
        for (i = 0; i<aBtn.length; i++){
            aBtn[i].style.background = 'yellow';
        }
    }
}

演算子

算術

  • + 加算
  • - 減算
  • * 乗算
  • / 除算
  • % 剰余(余りを求める)

代入

  • =
  • +=
  • -=
  • *=
  • /=
  • %=

関係

  • <
  • >
  • <=
  • >=
  • ==
  • !=
  • ===
  • !===

論理

  • && かつ(AND)
  • || または(OR)
  • ! 否定(NOT)

演算の優先順位

  • 括弧

プログラムのフロー制御

判断

  • if
  • switch (case break default)
  • ?:

ループ

  • while
  • for

抜け出す、スキップ

  • break
  • continue

真とは何か、偽とは何か

  • 真:ゼロでない数値、文字列、true、関数、オブジェクト:[] {} 見つけられる要素
  • 偽:ゼロ、NaN、空文字列、false、null、未定義、見つけられない要素

関数の戻り値 - returnの解説と応用

  • return 戻り値:関数名+括弧(例:fn1())は、その関数内でreturnの後に書かれた値を取得したことと同じです。
  • すべての関数のデフォルトの戻り値は:undefined
  • 返すことができるもの:数値、文字列、ブール値、関数、オブジェクト(要素、[]、{}、null)、未定義
  • returnの後にあるコードは一切実行されません。
alert fn1();
function fn1(){
    return function(){
        alert(1);
    }
}
このときポップアップ表示されるのは:function(){alert(1);}
alert fn1()();
function fn1(){
    return function(){
        alert(1);
    }
}
このときポップアップ表示されるのは1、つまりreturnされた匿名関数を実行した結果です。
alert fn1()(10);
function fn1(){
    return function(a){
        alert(a);
    }
}
このときポップアップ表示されるのは10です。
alert fn1(20)(10);
function fn1(a){
    return function(b){
        alert(a + b);
    }
}
このときポップアップ表示されるのは30です。

arguments

fn1(1, 2, 3); //実引数——実際に渡される引数 function fn1(a, b, c) //仮引数——形式上、a、b、cという名前が1、2、3を表す 仮引数を書かなくても、1、2、3を渡すことができ、すべてargumentsの中に格納されます。 function fn1(){ //arguments => [1, 2, 3] —— 実引数の集合(配列ではありませんが、配列に似ていて、lengthを持ち、添字でデータを取得することもできます) } 関数の引数の個数が確定できない場合は、argumentsを使います:
alert(sum(1,2,3));
function sum(){
    var n=0;
    for(var i=0; i<arguments.length; i++){
        n += arguments[i];
    }
    return n;
}
var a=1;
function fn2(a){ //arguments的某个数值就相当于某个形参
    arguments[0]=3;
    alert(a); //弹出3
    var a=2;
    alert(arguments[0]); //弹出2
}
fn2(a);
alert(a); //弹出1

currentStyleとgetComputedStyleの応用

  • getComputedStyleが取得するのはコンピューター(ブラウザ)が計算した後のスタイルですが、IE6、7、8とは互換性がありません。
  • currentStyleメソッドはIE6、7、8と互換性がありますが、標準ブラウザとは互換性がありません。
属性判定法、バージョン検出法でブラウザ間の互換性問題を解決します。 ~~~ js function getStyle( obj, attr) { return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle( obj )[attr]; } ~~~注意事項:
  • 上記の方法で background などの複合スタイルを取得する場合は、その方法で取得しないでください。ブラウザ間で互換性の問題があります。上記の方法は単一スタイルを取得するために使い、複合スタイルを取得するためには使わないでください。
  • 上記の方法を使うときは、余分なスペースを入れないよう注意してください。
  • 上記の方法を使うときは、未設定のスタイルを取得しないでください。ブラウザ間で互換性がないためです。
  • Firefox 4.0より前では、getComputedStyleの後に引数を付けないと問題が発生するバグがありました。そのため、getComputedStyle(obj, false)と書く人もいました。そのfalseはこのバグを解決するためのものです。ここは0でも、他の任意の引数でも構いません。ただし、現在のFirefoxはバージョンが高いため、この問題はあまり見られません。

タイマー

setInterval

setInterval(関数, ミリ秒); 繰り返し実行(エンジン)
var i=0;
function fn1(){
    document.title = i;
    i++;
}
setInterval(fn1, 1000);
イベント呼び出しの方法
  • fn1(); 直接呼び出し
  • document.onclick = fn1; イベント呼び出し
  • setInterval(fn1, 1000); 関数呼び出し
clearInterval
var timer = setInterval(函数, 毫秒); //重复执行
clearInterval(timer); //清除定时器
var i=0,
    timer = null;
function fn1(){
    i++;    
    document.title = i;
    
    if(i===10){
        clearInterval(timer);
    }
}
timer = setInterval(fn1, 1000);
注意タイマーがイベント(例:ボタンのonclick)で制御されている場合は、必ず「先にオフにしてからオンにする」という原則に従ってください。これにより、ボタンを連続クリックしてタイマーを重複設定することを防げます。また、clearInterval()は、中にtimerを入れても、nullでも、未定義でも、正常に動作します。

setTimeout

var timer = setTimeout(関数, ミリ秒); 1回だけ実行(爆弾) clearTimeout(timer);

タイマーの小応用(関数のカプセル化とコールバック関数)

doMoveの関数カプセル化

<input id="btn1" type="button" value="走" />
<div id="div1"></div>
var oBtn1 = document.getElementById('btn1');
var oDiv = document.getElementById('div1');

oBtn1.onclick = function () {
    
    doMove ( oDiv, 'left', 12, 900, function () {
        doMove ( oDiv, 'top', 34, 500 );
    });

};

//doMove函数封装

function doMove ( obj, attr, dir, target, endFn ) {
    
    dir = parseInt(getStyle( obj, attr )) < target ? dir : -dir;
    
    clearInterval( obj.timer );
    
    obj.timer = setInterval(function () {
        
        var speed = parseInt(getStyle( obj, attr )) + dir;          // 步长
        
        if ( speed > target &amp;&amp; dir > 0 ||  speed < target &amp;&amp; dir < 0  ) {
            speed = target;
        }
        
        obj.style[attr] = speed + 'px';
        
        if ( speed == target ) {
            clearInterval( obj.timer );
            
            /*
            if ( endFn ) {
                endFn();
            }
            */
            endFn &amp;&amp; endFn();
        }
        
    }, 30);
}

function getStyle ( obj, attr ) { 
    return obj.currentStyle?obj.currentStyle[attr] : getComputedStyle( obj )[attr]; 
}

震え(バウンス)の関数カプセル化

<img id="img1" src="img/4.jpg.html" />
<img id="img2" src="img/5.jpg.html" />
window.onload = function () {
    var oImg1 = document.getElementById('img1');
    var oImg2 = document.getElementById('img2');
    
    oImg1.onclick = fnShake;
    oImg2.onclick = fnShake;
    
    function fnShake() {
        var _this = this;
        shake( _this, 'left', function(){
            shake( _this, 'top' );
        });
    }

};

function shake ( obj, attr, endFn ) {
    var pos = parseInt( getStyle(obj, attr) ); //有隐患 需要解决
    var arr = [];           // 20, -20, 18, -18 ..... 0
    var num = 0;
    var timer = null;
        
    for ( var i=20; i>0; i-=2 ) {
        arr.push( i, -i );
    }
    arr.push(0);
        
    clearInterval( obj.shake );
    obj.shake = setInterval(function (){
        obj.style[attr] = pos + arr[num] + 'px';
        num++;
        if ( num === arr.length ) {
            clearInterval( obj.shake );
            endFn &amp;&amp; endFn();
        }
    }, 50);
}

システム時間オブジェクト

new Date(); //現在のシステム時刻オブジェクト
var myTime = new Date(); //myTime的类型是object
var iYear = myTime.getFullYear(); //获得年份
関連メソッド(以下で得られるものはすべて数値型):
  • getFullYear()
  • getMonth()
  • getDate()
  • getDay()
  • getHours()
  • getMinutes()
  • getSeconds()
注意事項:
  • getMonth()で取得する月は、1月が0から始まります。したがって、例えば現在が5月の場合、getMonth()で得られるのは4です。
  • getDay()で取得する曜日は数値です。現在が日曜日の場合、数字の0が得られます。

Dateオブジェクトのパラメータ

  • 数値形式:new Date(2013, 4 , 1 , 9 , 48 , 12); //年月日時分秒、月は0から始まることに注意。
var iNow = new Date();
var iNew = new Date(2014, 10, 26, 21, 56, 0);
var t = Math.floor((iNew - iNow)/1000); 
var str = Math.floor(t/86400) + '天' +  Math.floor(t%86400/3600) + '时' + Math.floor(t%86400%3600/60) + '分' +  t%60 + '秒';
  • 日:Math.floor(t/86400)
  • 時:Math.floor(t%86400/3600)
  • 分:Math.floor(t%86400%3600/60)
  • 秒:t%60
  • 文字列形式:new Date('June 10, 2013 12:12:12');
var iNow = new Date();
var iNew = new Date('November 10, 2013 21:56:0');
var t = Math.floor((iNew - iNow)/1000); 
var str = Math.floor(t/86400) + '天' +  Math.floor(t%86400/3600) + '时' + Math.floor(t%86400%3600/60) + '分' +  t%60 + '秒';

タイムスタンプ

getTime(); 1970年1月1日0時0分0秒0ミリ秒から現在までのミリ秒数を返します。

文字列操作

文字列取得系、数字を判定するメソッドのカプセル化

  • .lengthスペースも長さに含まれます。
  • .charAt()文字を取得します。括弧内に何も書かない場合、デフォルトで0番目の文字を取得します。文字列の長さ-1を超える場合は空文字を返します。
  • .charCodeAt()指定した文字のUnicodeエンコーディングを取得します。括弧内に何も書かない場合は、デフォルトで0番目の文字のUnicode値を取得します。括弧内の最小値は0、最大値は文字列の長さ-1です。
  • String.fromCharCode();文字コードに基づいて1文字を返します。例:String.fromCharCode(22937); は「妙」という文字を返します。複数の文字を取得するには、カンマで異なる文字コードを区切ります。例:String.fromCharCode(22937, 21916); は「妙味」の2文字を返します。0~9 => 48~57;a~z => 97~122;A~Z => 65~90
alert(detectNum(' 1a23d456'));
function detectNum(str){
    var n = 0;
    for(var i=0; i<str.length; i++){
        n = str.charAt(i);
        if( n < 48 || n > 57 ) {
            return false;
        }
    }
    return true;
}

indexOf、lastIndexOf

  • .indexOf()ある文字または文字列が文字列全体の中でどの位置にあるかを返します。str.indexOf('m', 5) は、str文字列の5番目から後方に文字mの位置を探すことを意味します。indexOf()で見つからない場合は-1を返します。左から右へ探します。2番目の引数が負の数の場合は、デフォルトで0として扱われます。
var str = 'サンプル - 学的不仅是技术,更是梦想!';
var s = 'サンプル';
var i = 0;

for ( ; str.indexOf(s, i) != -1; ){
    alert(str.indexOf(s, i));
    i = str.indexOf(s, i) + s.length;
}

或

while(str.indexOf(s, i) != -1) {
    alert(str.indexOf(s, i));
    i = str.indexOf(s, i) + s.length;
}
  • .lastIndexOf()右から左へ探します。数字の引数を指定して、どこから前に探し始めるかを指定することもできます。

比較系、切り出し系

  • 文字列の大小比較は、文字列の0番目の文字のUnicodeエンコーディングを比較します。
  • .substring(n, m)n番目からm番目までの文字を切り出します。mがない場合は、デフォルトで最後まで切り出します。str.substring(2, 0); と str.substring(0, 2); の結果は同じです。substringは2つの引数の大小を判定し、後の引数が前の引数より小さい場合は、自動的に2つの引数を入れ替えます。括弧内に引数がない場合は、0番目から最後まで、つまり文字列全体を切り出すことになります。引数に負の数がある場合は0として扱われます。
  • .slice(n, m)str.slice(0, 2) と str.slide(2, 0) は結果が異なります。後者は結果が見つかりません。なぜなら、.slice()メソッドは引数の大小を判定して位置を交換しないからです。str.slice(-2); は最後の1文字から最後から2番目までを切り出します。-1は最後の1文字を表します。str.slice(-4, -2); は最後から4番目から最後から2番目までの文字列を切り出します。

大文字・小文字変換、splitによる文字列分割

  • .toUpperCase()大文字に変換
  • .toLowerCase()小文字に変換
  • .split()文字列を配列に分割します。var str = 'www.miaov.com'; str.split('.'); => ["www", "miaov", "com"];var str1 = 'leo'; str1.split(); => ['leo'];str2 = 'leo'; str2.split(''); => ["l", "e", "o"];var str3 = '/www.miaov.com/'; str3.split('/'); => ["", "www.miaov.com", ""];var str4 = '2013-11-29-23-07'; str4.split('-', 3); => ["2013", "11", "29"]
  • .join()メソッドは、配列内の各要素を連結するために使用します。var arr = ['aa', 'bb', 'cc]; arr.join(); => 'aa,bb,cc' .join() の括弧内に何も書かない場合、デフォルトでカンマで区切られます。arr.join(''); => 'aabbcc' ; arr.join('-'); => 'aa-bb-cc'

文字列操作のまとめ

var str = 'サンプル-www.example.com';

str.charAt(1); // 3
str.charCodeAt(1); // 51
String.fromCharCode(119, 51); // w3

str.indexOf('c', 3); // 4
str.lastIndexOf('o'); // 25

'1000' < '2' // true
'1000' > 2 // true

str.substring(0, 4); // サンプル
str.slice(-3); // .cc

str.toUpperCase(); // サンプル-WWW.example.com
str.toLowerCase(); // サンプル-www.example.com

str.split('.', 2); // ["サンプル-www", "サンプル"]

var arr = ['www', 'サンプル', 'com'];
arr.join('.'); // www.example.com

配列の操作

jsonデータ形式と構文

var json = { name: 'leo', age: 32};
alert(json.name);

var imgData = { 
    url: ['img/1.png', 'img/2.png'],
    text: ['图片一', '图片二']
};
alert(imgData.url[1]);

var json2 = { 'name': 'miaov' }; //推荐的安全格式的写法
alert(json2.name);
alert(json2['name']);
json2.name = 'abc';
json2['name'] = '妙味'; //注意中括号里面要用引号

var arr = [{'name': 'TM', 'age': 23}, {'name': 'leo', 'age': 32}];
alert(arr[0].name);

for-inループ、jsonの走査

var json4 = { 'name': 'miaov', 'age': 3, 'fun': '前端开发'};
for(var attr in json4){
    alert(attr);
    alert(json4[attr]);
}

var json5 = { 
    url: ['img/1.png', 'img/2.png'],
    text: ['图片一', '图片二']
};

for(var attr in json5) {
    for(var i=0; i<json5[attr].length; i++){
        alert(json5[attr][i]);
    }
}
for-inはオブジェクトのプロパティも走査できます:
var str = '';
var num = 0;
for(var attr in window){
    str += num + '. ' + attr + ' : ' + window[attr] + '<br/>';
    num ++;
}
document.body.innerHTML = str;
配列もfor-inで走査できます:
var arr = ['a', 'b', 'c'];
for(var i in arr){
    alert(arr[i]);
}

配列のクリアと配列クリアの効率問題

// var arr = [1, 2, 3];
// var arr = new Array(1, 2, 3);

var arr = new Array(4);
alert(arr.length); // 4 在new Array()里面写了一个数字,就是定义了arr的长度
var arr = [1, 2, 3];
arr.length = 1; //数组的length属性是可写的
alert(arr);
var arr = [1, 2, 3];
arr.length = 0; //快速清空数组arr
或
arr = []; //通过重新赋值来清空数组,效率更高
var str = 'aaaaa';
str.length = 1;
alert(str); // 'aaaaa'
//字符串的length属性不可写,但是数组的length属性可写

配列の操作

追加
  • pushメソッド:arr.push(); 配列の最後に内容を追加します。.push()メソッドには戻り値があり、配列の新しい長さを返します。
  • unshiftメソッド:arr.unshift(); 配列の先頭に内容を追加します。戻り値は配列の新しい長さです(IE6、7はunshiftの戻り値をサポートしていません)
削除
  • popメソッド:arr.pop(); 配列の最後の要素を削除し、戻り値は削除された値です。
  • shiftメソッド:arr.shift(); 配列の最初の要素を削除し、戻り値は削除された値です。
小技
var arr = ['TM', '钟毅', '张森', '杜鹏', 'Leo'];
arr.unshift(arr.pop()); //数组变为:['Leo', '钟毅', '张森', '杜鹏', 'TM']
或
arr.push(arr.shift()); //数组变为:['钟毅', '张森', '杜鹏', 'Leo', 'TM']
spliceメソッド
  • spliceメソッドには削除、置換、追加の3つの機能があります。
var arr = ['TM', '钟毅', '张森', '杜鹏', 'Leo'];
//删除
//arr.splice(0, 1); //删掉第0位,删1个。两个参数第一个是从第几位开始,第二个是删掉几个。splice删除的时候有返回值,返回的是被删除的内容
//替换
//arr.splice(0, 1, '莫涛'); //替换第0位,替换1个,替换为'莫涛'。返回的还是删除的东西
//添加
arr.splice(1, 0, '李贤'); //在第1位那里,删除0个,添加了一个'李贤'到了第1位,'钟毅'就变成了arr[2]了。后面也可以添加多个。如果splice删除了0个,那么就没有返回值。

配列の重複除去

var arr = [1, 2, 2, 4, 2];
for ( var i=0; i<arr.length; i++ ) {
    for ( var j = i+1; j<arr.length; j++) {
        if( arr[i]==arr[j] ){
            arr.splice( j, 1 );
            j--;
        }
    }
}
sortソート
var arr = ['c', 'd', 'a', 'e'];
arr.sort(); // 'a', 'c', 'd', 'e' 按照unicode编码排序

var arr2 = [4, 3, 5, 76, 2, 0, 8];
// arr2.sort(); // 0, 2, 3, 4, 5, 76, 8 sort默认是将数组中的每一个按照字符串来排序的,因此出现了76排在8前面的情况

// arr2. sort(function( a, b ){
    return a - b; //如果a-b返回正数,就a、b两个数字换个序。如果a-b是负数,就不换序
}) //返回数字从小到大 0, 2, 3, 4, 5, 8, 76

// arr2. sort(function( a, b ){
    return b - a;
}) //返回数字从大到小 76,, 8, 5, 4, 3, 2, 0
その他のソート方法:
  • クイックソート
  • シェルソート
  • バブルソート
  • マージソート
  • 選択ソート
  • 挿入ソート
var arrWidth = ['345px', '23px', '10px', '1000px'];
arrWidth.sort(function(a, b){
    return parseInt(a) - parseInt(b);
}); // ['10px', '23px', '345px', '1000px']
ランダムソート
var arr = [1, 2, 3, 4, 5, 6, 7, 8];
arr.sort(function(a, b){
    return Math.random(); - 0.5;
});

乱数と乱数公式の導出過程

Math.random(); 0〜1の間の乱数を返します。 整数の0と1をランダムに返したい場合は、四捨五入を使用します: Math.round(Math.random()); // 注意、ここではMath.floorは使用できません 0〜10の間の乱数を返したい場合: Math.round(Math.random() * 10); // 0〜10の間のランダムな整数を返します 20〜100の間の乱数を返す場合: Math.round( Math.random()*80 + 20 ); // 5〜10の間のランダムな整数を返します xからyまでの整数を返したい場合は: Math.round( Math.random() * (y - x) + x ); 0〜xの整数を返す場合: Math.round( Math.random() * x ); 1〜xの整数を返す場合: Math.ceil( Math.random() * x ); // Math.ceil() は切り上げですconcatメソッドconcatメソッドは配列を連結するために使用します。
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

arr1.concat(arr2); //[1, 2, 3, 4, 5, 6] 新数组与原来数组没什么关系。
arr1.concat(arr2, arr3); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
reverseメソッドreverseメソッドは配列内の順序を逆にします。元の配列が変更されます。
var arr1 = [1, 2, 3];
arr1.reverse();
alert(arr1); // [3, 2, 1]
var str = 'abcdef';
alert(str.split('').reverse().join('')); //'fedcba'

参考資料

その他のチュートリアルは、こちらからアクセスできます。JavaScript チュートリアル。