原著者: Andy Croxall
元のリンク: Ten Oddities And Secrets About JavaScript
翻訳編集者: Zhang Xinxu
データ型と定義
1. Null はオブジェクトです
JavaScript の多くの型の中に、null という一意の値を持つ Null 型があります。 、そのリテラルは、まったく意味のない値として定義されます。次の検出コードに示すように、オブジェクトのように動作します:
alert (typeof null) // 以下に示すように 'object'
をポップアップします。
typeof 値は「object」を示しますが、null はオブジェクト インスタンスとは見なされません。ご存知のとおり、JavaScript の値はオブジェクト インスタンスであり、各値は Number オブジェクト、各オブジェクトは Object オブジェクトです。 null には値がないため、null が何かのインスタンスではないことは明らかです。したがって、以下の値は false と等しくなります。
翻訳者注: null はオブジェクトのプレースホルダーとしても理解できます
2. NaN は数値です
NaN の本来の意味値は数値ではありませんが、数値そのものではありません。次のコードを見てください:
コードをコピー
コードは次のとおりです: alert(typeof NaN) //pop up 'Number' alert(NaN === NaN); ); // false
結果は次のとおりです:
実際、NaN は何とも等しくありません。何かが NaN であるかどうかを確認するには、isNaN のみを使用できます。
3. キーワードのない配列は false と同等です (Truthy と Falsy について)
ここに、JavaScript のもう 1 つの大きな癖があります。 >
コードをコピー
結果は次のようになります:
ここで何が起こっているのかを理解するには、真実と虚偽の概念を理解する必要があります。これらは true/flase リテラルです。 JavaScript では、すべての非ブール値には組み込みのブール値フラグがあり、ブール値と比較する場合など、値がブール値として動作する必要がある場合に、この組み込みのブール値が表示されます。
リンゴとナシを比較することはできないため、JavaScript で 2 つの異なるタイプの値を比較する必要がある場合、まずそれらを同じタイプに弱めます。 false、unknown、null、0、""、NaN はすべて false に弱められます。この強制は常に存在するわけではなく、式として使用される場合にのみ存在します。次の簡単な例を見てください:
コードをコピーします
結果は次のとおりです:
上記のテストでは、値 0 とブール値 false を比較しようとしました。この 2 つのデータ型には互換性がないため、JavaScript は自動的に統合された同等の true と false に強制的に変換します。ここで、0 は false に相当します (前述のとおり)。上記)に言及)。
上記の値の一部には false に相当する空の配列がないことに気づいたかもしれません。空の配列は奇妙なものであるため、それ自体は実際には真実ですが、空の配列をブール型と比較すると、その動作は偽になります。わからない?これには理由があります。空の配列の奇妙な動作を検証する例を見てみましょう:
var someVar = []; //空の配列
alert(someVar == false) //結果は true
if (someVar) alter('hello');ステートメントが実行されるため、someVar は true として扱われます
結果は以下のスクリーンショットに示すようになり、2 つのボックスが連続してポップアップ表示されます:
翻訳者注: この違いの理由は、著者によれば、配列には組み込みの toString() メソッドがあるためです。たとえば、直接アラートを送信すると、文字列が join(" の形式でポップアップされます。 ,”)、空の配列は当然空の文字列であるため、false と同等になります。詳細については、著者の別の記事「Twistedlogic:truthy & falseyを理解する」を参照してください。しかし、私が個人的に不思議に思うのは、空のオブジェクト、空の関数、weak が true または false に等しい場合、「Why?」と表示されることです。それは本当に、配列が奇妙なもので特別な考慮が必要だからでしょうか?
キャストによる比較の問題を回避するには、弱い等号 (==) の代わりに強い等号 (===) を使用します。
var someVar = 0; (someVar = = false); //結果 true – 0 は false に属します
alert(someVar === false); //結果 false – ゼロはブール値ではありません
結果は以下のスクリーンショットのようになります (win7 FF4):
JavaScript の型強制などの固有の癖をさらに詳しく知りたい場合は、公式の関連文書仕様を参照してください:
ECMA-262 のセクション 11.9.3正規表現の式
4. replace() はコールバック関数を受け入れることができます
これは、v1.3 で初めて導入された JavaScript の最も知られていない秘密の 1 つです。ほとんどの場合、replace() の使用法は次のようになります:
alert('10 13 21 48 52'.replace(/d /g, '*')) //すべての数字を *
に置き換えます。これは単純です置換、1 文字の文字列、アスタリスク。しかし、置換のタイミングをより詳細に制御したい場合はどうすればよいでしょうか? 30 未満の値のみを置き換えたいのですが、どうすればよいでしょうか?現時点では、正規表現だけに頼ることはできません。各一致を処理するにはコールバック関数を使用する必要があります。
alert('10 13 21 48 52' .replace( /d /g, function(match) {
return parseInt(match) }));
各一致が完了すると、JavaScript はコールバック関数を適用し、一致したコンテンツを match パラメーターに渡します。その後、コールバック関数のフィルタリング ルールに応じて、アスタリスクが返されるか、一致自体が返されます (置換は行われません)。
以下のスクリーンショット:
5. 正規表現: 一致と置換だけではない
多くの JavaScript エンジニアは、一致と置換によってのみ正規表現を扱います。しかし、JavaScript で定義されている正規表現関連のメソッドは、これら 2 つよりもはるかに多くあります。
test() は match() と同様に機能しますが、戻り値が異なります。test() は一致するかどうかを確認するために使用されるブール型を返し、実行速度は match() よりも高速です。マッチ()。
alert(/w{3,}/ .test( 'Hello')); //Pop up 'true'
上記のコード行は、文字列に 3 つ以上の通常の文字が含まれているかどうかを確認するために使用されます。要件があるため、true が表示されます。
結果は次のとおりです:
また、動的な正規表現オブジェクトの作成に使用できる RegExp オブジェクトにも注意する必要があります。次に例を示します。
function findWord(word, string) {
var instantsOfWord = string.match(new RegExp('\b' word '\b', 'ig'));
alert(instancesOfWord)
}
findWord('car', 'カールは車を買いに行きましたが、クレジット カードを忘れてしまいました。');
ここでは、パラメーターの単語に基づいて一致検証を動的に作成します。このテスト コードの機能は、大きな選択と小さな選択を区別せずに単語 car を選択することです。ざっと見たところ、テスト英語の文にある単語は car だけなので、ここでのパフォーマンスは 1 単語だけです。単語の境界を表すために使用されます。
結果は次のとおりです:
関数とスコープ
6. スコープのふりをすることができます
スコープは、ウィンドウオブジェクト内で独立した JavaScript (実行中の関数にない JavaScript など) が利用可能な変数を決定するために使用されます。グローバル スコープでは、ウィンドウ オブジェクトにはどのような状況でもアクセスできます。ただし、関数内で宣言されたローカル変数は、その関数内でのみ使用できます。
var Animal ='dog'; >function getAnimal (形容詞) {alert(adjective '' this.animal); }
getAnimal('lovely') //ポップアップ '素敵な犬'
ここで変数と関数を示します。グローバルスコープで宣言されています。これは現在のスコープ (この例ではウィンドウ) を指しているためです。したがって、この関数は window.animal (「dog」) を探します。ここまでは順調ですね。ただし、実際には、関数を別のスコープで実行し、それ自体のスコープを無視することができます。 call() という組み込みメソッドを使用して、スコープの偽装を実現できます。
var Animal ='dog'; >関数 getAnimal (形容詞) {alert(形容詞 '' this.animal) };
var myObj = {animal: 'ラクダ'}; //pop up 'lovely Camel' '
call() メソッドの最初のパラメーターは、関数内で this であるように見せることができます。したがって、ここでの this.animal は実際には myObj.animal、つまり 'camel' です。 。後続のパラメータは通常のパラメータとして関数本体に渡されます。
もう 1 つの関連するメソッドは apply() メソッドです。これは call() と同じように機能しますが、関数に渡されるパラメーターが独立変数ではなく配列の形式で表される点が異なります。したがって、上記のテスト コードを apply() で表すと、次のようになります。
コードをコピーします
コードは次のとおりです。 getAnimal.apply(myObj, ['lovely']); //関数パラメータは配列の形式で送信されます
デモ ページで、最初のボタンをクリックした結果は次のようになります:
2 番目と 3 番目のボタンをクリックした結果は次のようになります:
7.関数自体は実行できます
以下は問題ありません:
(function() {alert('hello'); })() // 'hello' をポップアップします
ここでの解析は非常に簡単です: 関数を宣言します() 解析のため、すぐに実行されます。なぜこれを行うのか (直接 () 呼び出しを参照) と不思議に思うかもしれませんが、これは少し矛盾しているように思えます。関数には通常、今すぐ解析して実行するのではなく、後で実行したいコードが含まれています。そうでない場合は、解析する必要はありません。関数にコードを入れます。
自己実行関数 (SEF) のもう 1 つの有効な使用法は、イベント コールバック、タイムアウト、実行間隔 (間隔) など、遅延コードでバインドされた変数値を使用することです。次の例:
var someVar ='hello ';
setTimeout(function() {alert(someVar); }, 1000);
var someVar ='goodbye';
タイムアウトが発生する理由をフォーラムでよく質問します。代わりにここでお別れです、こんにちはではないですか?答えは、タイムアウト時のコールバック関数は、実行されるまで someVar 変数の値を割り当てないからです。当時、someVar は長い間、goodbye によって書き換えられていました。
SEF は、この問題の解決策を提供します。上記のようにタイムアウト コールバックを暗黙的に指定する代わりに、someVar 値がパラメータとして直接渡されます。この効果は重要です。つまり、someVar 値を渡して分離し、地震、津波、またはガールフレンドが轟音を立てているかどうかに関係なく、値が変更されないように保護します。
var someVar = 'hello'; >setTimeout((function(someVar) {
returnfunction() {alert(someVar); }
})(someVar), 1000);
状況は変わり、今度はここのポップアップが hello になりました。これが関数パラメータと外部変数の違いです。
たとえば、最後のボタンをクリックした後のポップアップは次のとおりです:
ブラウザ
8. FireFox は 16 進数ではなく RGB 形式で色を読み取って返します
今までよくわかりませんでしたなぜ Mozilla このようになります。明確に理解するために、次の例を見てください:
コードをコピーします
コードは次のとおりです: こんにちは! p>
< ;script>
var ie = navigator.appVersion.indexOf('MSIE') !=-1;
var p = document.getElementById('somePara');つまり? p.currentStyle.color :
ほとんどのブラウザのポップアップ結果は ff9900 ですが、FireFox の結果は RGB 形式の rgb(255, 153, 0) です。多くの場合、色を扱う場合、RGB カラーを 16 進数に変換するために大量のコードを費やす必要があります。
以下は、上記のコードをさまざまなブラウザで実行した結果です:
その他のその他
9. 0.1 0.2 !== 0.3
この奇妙な問題は JavaScript でのみ発生するわけではありません。 、これはコンピューター サイエンスにおける一般的な問題であり、多くの言語に影響を与えます。タイトルの式は 0.30000000000000004 を出力します。
これは機械精度と呼ばれる問題です。 JavaScript がコードの (0.1 0.2) 行を実行しようとすると、値を優先バイナリ形式に変換します。ここから問題が始まります。0.1 は実際には 0.1 ではなく、バイナリ形式です。基本的に、これらの値を書き留めると、精度は必ず失われます。単純な小数点以下 2 桁が必要なだけかもしれませんが、得られるものは (Chris Pine のコメントによると) 2 進浮動小数点計算です。たとえば、段落を簡体字中国語に翻訳したいが、結果が繁体字になった場合でも、依然として違いが存在します。
これに関連する問題に対処するには、一般に 2 つの方法があります。
整数に変換してから計算し、計算が完了したら目的の 10 進数の内容に変換します。
ロジックを調整して権限を設定します。範囲は指定された結果ではありません。
たとえば、次のようにはなりません:
var num1=0.1, num2=0.2, shouldEqual=0.3;
alert(num1 num2 == shouldEqual); //false
そして、これを試すことができます:
alert(num1 num2 > shouldEqual - 0.001&& num1 num2 < shouldEqual 0.001); // true
10. 未定義は定義できます
最後は、穏やかで霧雨のような小さな風変わりな話で終わります。奇妙に聞こえるかもしれませんが、未定義は JavaScript の予約語ではありませんが、これには特別な意味があり、変数が未定義かどうかを判断する唯一の方法です。したがって:
コードをコピーします コードは次のとおりです。 (someVar = = unknown); //Show true
これまでのところ、すべてが穏やかで正常に見えますが、プロットは常に血まみれです:
コードをコピーします
alert(someVar; == unknown ); // Display false!
これが、jQuery ソース コードの最も外側のクロージャー関数に渡されない unknown パラメーターがある理由です。外部の悪者によって利用されます。