式はJavaScriptのフレーズであり、JavaScriptインタープリターが結果を計算します。プログラムで一般的に使用される量は、変数である最も単純な式のタイプです。変数名も単純な式であり、その値は変数に割り当てられた値です。
複雑な表現は、単純な表現で構成されています。たとえば、配列アクセス式は、配列、正方形の括弧、および整数式を表す式で構成されています。それらが形成する新しい式操作は、配列の特定の位置での要素値です。同じ手紙
番号コール式は、関数オブジェクトを表す式と0個以上のパラメーター式を表す式で構成されています。単純な式を複雑な式に組み合わせる最も一般的な方法は演算子です。
この章(この記事)では、すべてのJavaScriptオペレーターについて説明します。また、演算子(配列要素や関数呼び出しへのアクセスなど)を伴わない表現を説明し、その構文とプログラミングスタイルはC言語の構文とプログラミングスタイルと非常に似ています。
1。要素式
最も単純な式は「元の式」であり、これは式の最小の単位であり、他の式は含まれていません。 JavaScriptの元の式には、定数または直接量が含まれています。キーワードと変数。
直接的な数量は、プログラムに直接表示される一定の値です。彼らは次のように見えます:
コードコピーは次のとおりです。
1.23 //直接数
「こんにちは」//直接的な数量
/ pattern //正規表現直接数量
JavaScriptのいくつかの予約された単語は、元の式を形成します
コードコピーは次のとおりです。
true // boolean値:true
false // false
null //値を返します:空
これは//「現在」オブジェクトを返します
第3章の学習を通じて、他のキーワードとは異なり、これは定数ではなく、プログラムのさまざまな部分で返す値も異なります。このキーワードは、多くの場合、オブジェクト指向のプログラミングに表示されます。これにより、正方形のメソッドのオブジェクトが返されます。
最後に、3番目の元の式は変数です
コードコピーは次のとおりです。
i //変数iの値を返します
合計//合計値を返します
未定義の//は、nullとは異なり、キーワードではありません。
2。オブジェクトと配列の初期化式。
オブジェクトと配列の初期化は、実際には新しく作成されたオブジェクトと配列です。これらの初期化された式は、「オブジェクト直接数量」と「配列直接数量」と呼ばれることもあります。ただし、ブールの直接量とは異なり、メンバーまたは要素がサブ発現であるため、それらは元の表現ではありません。
配列の初期化式の構文は非常にシンプルです。以下に始めましょう
配列の初期化式は、一対の四角い括弧とコンマ区切りリストで構成されています。初期化の結果は、新しく作成された配列です。配列の要素は、式のコンマ区切り値です。
[] //空の配列; []その中に空のままにしておくことは、配列に要素がないことを意味します
[1+2,3+4] // 2つの要素を持つ配列、最初の要素は3、2番目は7です
配列初期化式の要素初期化式は、配列初期化式にすることができます。つまり、表現はネストできます
コードコピーは次のとおりです。
var mat = [[1,2,3]、[4,5,6]、[7,8,9]];
配列内のリスト間の要素は省略でき、スペースは未定義で満たされます。例えば:
コードコピーは次のとおりです。
var a = [1 ,,,, 5]
4つの要素は未定義です。アレイの直接数量の端にコンマが残されており、未定義の値の新しい要素は作成されません。
オブジェクトの初期化式は、四角いブラケットが巻き毛ブラケットに置き換えられていることを除いて、配列の初期化式に非常に似ています。また、各単語式には、属性名とプレフィックスとしての非コロンが含まれています。
コードコピーは次のとおりです。
var p = {x:2.1、y:-3} // 2つの属性メンバーを持つオブジェクト
var q = {}; //空のオブジェクト
QX = 2.1; Qy = -3; // Qの属性メンバーはPの属性メンバーと同じです
たとえば、オブジェクトは直接ネストすることもできます
コードコピーは次のとおりです。
var anh = {左:{x:2、y:3}、
右:{x:4、y:5}}
JavaScriptがオブジェクト初期化式の値を計算すると、オブジェクト式は毎回計算され、一定の値を含める必要はありません。同様に、オブジェクトの直接数量内のプロパティの名前は、識別子の代わりに文字列にすることができます。 (予約された単語または一部の違法な識別子のみがその行の属性名として使用される場合、非常に便利です)
コードコピーは次のとおりです。
var Side = 1;
var square = {"left":{x:px、y:py}、
「右」:{x:p.x+side、y:p.y+side}}
第67章では、オブジェクトと配列の初期化式についても再度説明します。
3。関数式
関数定義式は、JavaScript関数を定義します。式の値は、この新しく定義された関数です。ある意味では、関数定義式は直接関数の量になり、関数式は「直接関数量」と呼ばれます。典型的な関数定義式には、キーワード関数が含まれ、その後に括弧のペア、コンマ分離リストが含まれ、リストには0以上の識別子(パラメーター名)が含まれます。次に、巻き毛の装具に包まれたJavaScriptコードセグメント(関数本体)に従います。
var square = function(x){return x*x};
関数定義式には、関数の名前も含めることができます。関数は、関数式ではなく、関数ステートメントによって定義することもできます。より多くのコンテンツについては、第8章で説明します。
4。属性アクセス式
属性アクセス式操作は、オブジェクトまたは配列要素の値を取得します。 JavaScriptは、プロパティアクセスの2つの方法を定義します。
コードコピーは次のとおりです。
表現 。 dentifier
式[式]
最初の方法は、式とその後の識別子が続くことです。式はオブジェクトを指定し、識別子はアクセスする属性ミンチュアンを指定します。
第2章は、式である正方形の括弧を使用して書かれています(この方法はオブジェクトと配列に適しています)。 2番目の式は、アクセスするMingchuanプロパティまたはアクセスする配列要素を表すインデックスを指定します。ここにいくつかの具体的な例があります
コードコピーは次のとおりです。
ox // => 1x式の属性o
oyz // => 3 z式oyの属性
o。["x"] // => 1オブジェクトoのx属性
a [1] // => 4式aのインデックスを持つ要素は1です
a [2] ["1"] // => 6式A [2]のインデックス1を持つ要素
a [0] .x // => 1:x x属性a [0]
使用される属性アクセス式の形式に関係なく、「前の式」。 「["は常に最初に評価されます。評価結果がnullまたは未定義の場合、これらの値のいずれも属性を含めることができないため、式はタイプエラーの例外をスローします。操作結果がオブジェクトまたは配列でない場合、JavaScriptはそれをオブジェクトに変換します(第3章、セクション6)
.identifierはより簡単に記述されますが、このメソッドはアクセスする属性名にのみ適用され、法的識別子であることに注意する必要があります。そして、アクセスへの属性の名前を知る必要があります。プロパティ名が予約済みの単語であるか、スペースと句読点が含まれ、数字(配列用)が含まれている場合は、正方形の括弧を書く必要があります。属性名が固定値ではなくオペレーターから派生した値である場合、正方形の括弧を書く必要があります。 (第6章、2、1バー)
5。輸送表現
JavaScriptの呼び出し式は、関数またはメソッドを呼び出す(または実行)の構文表現です。それは、呼び出される関数を指す関数式から始まります。関数式の後に、コンマ分離されたパラメーターリストを備えた括弧のペアが続きます。 0パラメーターまたは複数のパラメーターがあります。
f(0)// fは関数式です:0はパラメーター式です。
math.max(x、y、z)//math.maxは関数です。 x、y、zはパラメーターです
a.sort()//a.sort()は、パラメーターを持たない関数です。
式が評価のために呼び出されたら、最初に関数式を計算し、次にパラメーター式を計算してパラメーター値のセットを取得します。関数式の値が呼び出し可能なオブジェクトではない場合、タイプエラーの例外がスローされます。パラメーターの値は、関数を定義するときに定義される正式なパラメーターに割り当てられます。次に、関数本文を実行します。関数が返品ステートメントを使用して戻り値を与える場合、この返品値は呼び出し式全体の値です。それ以外の場合、呼び出し式の値は未定義です。関数呼び出しの詳細 - 正式なパラメーター式の数と関数定義の実際のパラメーターの数を含む - は、第8章で詳しく説明します。
呼び出し式には、左の括弧の前の括弧と式のペアが含まれています。この式がプロパティアクセス式である場合、この呼び出しは「メソッド招待状」と呼ばれます。メソッド呼び出しで関数本文を実行する場合、属性としてアクセスされるオブジェクトと配列は、呼び出しメソッドのこのポインターです。この機能により、関数(OO名が「メソッド」)がホストオブジェクトを呼び出すことができます(詳細は第9章で詳しく説明します)。
6。オブジェクト作成式
オブジェクト作成式はオブジェクトを作成し、関数(コンストラクター)を呼び出してオブジェクトのプロパティを初期化します。オブジェクトの作成式は、オブジェクト作成式の前に新しいキーワードが新しいキーワードがあることを除いて、関数呼び出し式と非常に似ています。
new object()
新しいポイント(2,3)
オブジェクト作成式がコンストラクターにパラメーターを渡す必要がない場合、このブラケットのペアは省略できます。コンストラクターの詳細については、第9章で説明します。
新しいオブジェクト
新しいポイント
7。オペレーターの概要
JavaScriptの演算子は、テーブル式、比較式、論理式、割り当て式などを計算するために使用されます。
ほとんどの演算子は、削除やInstanceofなどの句読点で表されることに注意する必要があります。キーワード演算子であろうとシンボリック演算子であろうと、代表者は通常の演算子であり、その構文は非常に簡潔です。
下付き文字演算子の優先順位はソートされており、以前の演算子の優先度は後続の演算子の優先度よりも高くなっています。 Horizontal Huafengで区切られたオペレーターには、優先順位が異なります。
Aは、オペレーターの結合性を表します。
l左から右またはr(右から左へ)
タイトルnのリストは、オペランドの数を表します。
タイプは、予想されるオペランドのタイプとオペレーターの結果タイプを表します(「→」シンボルの後)
| オペレーター | 動作します | a | n | タイプ |
| ++ | フロント/増分後 | r | 1 | lval→num |
| - | 前後に減らします | r | 1 | lval→num |
| - | 逆を求めます | r | 1 | num→num |
| + | 数字に変換します | r | 1 | num→num |
| 〜 | 少しずつ逆にします | r | 1 | int→int |
| ! | 論理的ではない | r | 1 | ブール→ブール |
| 削除削除 | 属性を削除します | r | 1 | lval→bool |
| typeof | 操作タイプを検出します | r | 1 | Any→Str |
| 空所 | 未定義の値を返します | r | 1 | ANY→UNDEF |
| *、 /、% | 乗算して分割して残りを見つけます | l | 2 | num、num→num |
| +、 - | 追加、減算します | l | 2 | num、num→num |
| + | 文字列接続 | l | 2 | str、str→str→str |
| << | 左シフト | l | 2 | int、int→int |
| >> | 正しいシフト | l | 2 | int、int→int |
| >>> | 署名されていない権利 | l | 2 | int、int→int |
| <、<=、>、> = | 数字の順序を比較します | l | 2 | num、num→bool |
| <、<=、>、> = | 文字の順序を比較します | l | 2 | str、str→bool |
| instanceof | オブジェクトクラスをテストします | l | 2 | obj、func→bool |
| で | 属性が存在するかどうかをテストします | l | 2 | str、obj→bool |
| == | 平等な判断 | l | 2 | 任意の、すべての→ブール |
| ! = | 不満の判断 | l | 2 | 任意の、すべての→ブール |
| === | 資質を判断します | l | 2 | 任意の、すべての→ブール |
| ! == | 裁判官は一定ではありません | l | 2 | 任意の、すべての→ブール |
| & | ビットワイズと | l | 2 | int、int→int |
| ^ | ビットワイズxor | l | 2 | int、int→int |
| | | ビットワイズまたは | l | 2 | int、int→int |
| && | ロジックと | l | 2 | 任意の、任意→任意 |
| || | 論理的または | l | 2 | 任意の、任意→任意 |
| ?: | 条件付き演算子 | r | 3 | ブール、任意、任意の→任意 |
| = | 可変割り当てまたはオブジェクト属性の割り当て | r | 2 | lval、Any→Any |
*= /=%= += - =&= ^= | = << = >> = >>> = | 値を計算して割り当てます | r | 2 | lval、Any→Any |
| 、 | 最初のオペランドを無視して、 2番目のオペランドを返します。 | l | 2 | 任意の、任意→任意 |
私。オペランドの数
オペレーターは、オペランドの数によって分類できます。
JavaScriptのほとんどの演算子は、2つの式を少し複雑な式に組み合わせたバイナリ演算子です。
JavaScriptは、ある式を別のより複雑な式に変換するいくつかの単位オペレーターもサポートしています。式-Xの「 - 」演算子は、単位演算子です。 xの負の値を見つけることです。
JavaScriptは、3つの式を1つの式に結合する条件付き判断オペレーター "?:"をサポートします。
ii。オペランドの種類と結果タイプ
一部の演算子は、任意のデータ型に使用できますが、それでも指定された型のデータを動作させることを望んでいます。
iii.lvalue
課題演算子およびテーブル内の他の少数のオペレーターは、オペランドのlvalタイプを期待しています。LValueは古代の用語です。それは、「式は割り当て演算子の左側にのみ表示できる」ことを意味します。 JavaScriptでは、変数、オブジェクトプロパティ、および配列要素はすべてLValuesです。 ECMAScriptの仕様により、範囲内蔵機能がLValueを返すことができますが、定義された関数はLValueを返すことはできません。
IIII。オペレーターの優先順位
上の表では、示されている演算子は優先度によって高から低いものに分類されており、各水平分離器内のオペレーターのセットが同じ優先度を持っています。オペレーターの優先度は、オペレーターが実行される順序を制御します。高い(テーブルの上部)のオペレーターは、常に優先度が低い(テーブルの下部)のオペレーターよりも高く実行されます。
次の式を参照してください
w = x+y*z;
乗算演算子「*」は、追加「+」よりも優先度が高いため、乗算が最初に実行されます。次に、割り当て演算子 "="の優先順位が最も低いためです。したがって、割り当て操作は、右の式が結果を計算した後に実行されます。
オペレーターの優先順位は、ガーデンブラケットを使用して記述できます。上記の式はこのように書くことができます。
w =(x + y) * z;
プロパティアクセス表現と呼び出し式の優先順位は、表のすべての演算子の優先順位よりも高いことに注意してください。
my.functionのタイプ[x](y)
TypeOFは最も優先度の高い演算子の1つですが、TypeOFは2つのプロパティアクセスと関数呼び出しの後にも実行されます。
実際、使用しているオペレーターの優先順位が本当にわからない場合は、最も簡単な方法は、庭の括弧を使用して運用順序を強制することです。いくつかの重要なルールを記憶する必要があります。乗算と分裂は追加と減算よりも高く、割り当て操作の優先順位は非常に低く、通常は最後に実行されます。
iiiiiii.operationality
このセクションでは、Aタイトルの列には、オペレーターの節度が示されています。 lは左から右への組み合わせを指し、Rは右から左への組み合わせを指します。結核は、同じ優先順位を持つ複数のオペレーター式の操作順序を指定します。
たとえば、減算操作は左から右に組み合わせて実行されます。
コードコピーは次のとおりです。
w = x -y -z
このコードのように:
コードコピーは次のとおりです。
w =((x -y)-z)
逆に、次の式:
コードコピーは次のとおりです。
x =〜-y;
w = x = y = z;
q = a?b:c?d:e?f:g;
このコードとまったく同じです
コードコピーは次のとおりです。
x =〜(-y);
w =(x =(y = z));
q = a?b:(c?d:(e?f:g))
単位オペレーター、割り当て、および三元状態のオペレーターはすべて、右から左に組み合わされているためです。
iiiiiiiii.operation順序
オペレーターの優先順位と拘束力は、割り当て方程式での操作の順序を定義しますが、単語表現の計算プロセスで操作の順序を指定しません。 JavaScriptは、常に次のように、常に式を厳密に順番に計算します。
式w = x+y*zでは、式wが最初に計算され、次にx、y、zが計算され、yの値にzが掛けられ、xの値が追加されます。最後に、その式wで言及される変数または属性が参照されます。式にサークルブラケットを追加すると、乗算、追加操作、割り当て操作の関係が変わります。しかし、左から右への順序は変わりません。
8。算術式
このセクションでは、これらの算術計算演算子と、オペランドの算術演算について説明します。乗算、分割、および減算演算子は非常に簡単です。追加操作は別のセクションです。追加オペレーターは文字列連結を動作させることができ、そのタイプ変換はやや特別なものです。
基本的な算術演算子は *、 /、%、 +、 - です。 +の追加に加えて、他の演算子は特に簡単です。必要に応じて数値に変換されるだけで、製品、商、残差(モジュール)、差を見つけることができます。数値に変換できないすべての操作は、NAN値に変換されます。オペランド(または変換結果)がNAN値である場合、算術演算の結果もNANです
整数と浮動点を区別するプログラミング言語を使用している場合、オペレーター "/"は2番目のオペランドを最初のオペランドで分割します。次に、整数を整数で分割すると、目的の結果も整数です。 JavaScriptでは、すべての数値が浮動小数点数であり、分割操作の結果も浮動小数点タイプです。たとえば、5/2の結果は2ではなく2.5です。Nivisor0の操作の結果は、正の無限または負の無限です。 0/0の結果はnanです。これらすべての操作はエラーを報告しません。
演算子の「%」は、最初のオペランドのモジュラスを2番目のオペランドに計算します。つまり、最初のオペランドは2番目のオペランドの残りの部分で分割されます。結果シンボルは、最初の操作マウス(分割)シンボルと一致しています。たとえば、5%2の結果は1、-5%2は-1です。
残りのオペレーターのオペランドは通常、整数ですが、浮動小数点数にも適しています。 6.5%2.1結果は0.2です。 (0.199999999999999973)
私。 「+」オペレーター
バイナリ追加演算子 "+"は、2つの数字または文字列連結操作を追加できます。
コードコピーは次のとおりです。
1+2 // => 3
「Hello " +" " +" there "// =>"こんにちは "
"1"+"2" // => "12"
両方のオペランドが数字であるか、文字列である場合、計算結果は明らかです。ただし、他の場合には、必要なタイプ変換が必要です。また、オペレーターの動作は、タイプの変換の結果に依存します。技術的に言えば、追加演算子の動作は次のとおりです。
オペランドがオブジェクトである場合、オブジェクトはオブジェクトの変換ルールに従って元のクラス値に元の値に従います(第3章、セクション8、3を参照)。日付はオブジェクトtoString()メソッドで変換を実行しますが、他のオブジェクトはvalueof()メソッドを介して変換を実行します(valueof()メソッドがプリミティブ値を返す場合)。ほとんどのオブジェクトには利用可能なvalueof()メソッドがないため、toString()メソッドを使用してクロールを実行します
元の値へのオブジェクトが変換された後、操作の1つが文字列の場合、もう1つのオペランドも文字列に変換されます。次に、文字列連結を行います。
それ以外の場合、両方のオペランドが数字(またはnan)に変換され、追加されます。
ここにいくつかの例があります
コードコピーは次のとおりです。
1 + 2 // => 3追加
"1" + "2" // => "12"文字列接続
"1" + 2 // => "12"数字は文字列に変換され、連結されています
1 + {} // => "1 [Object Object]":オブジェクトは文字列に変換され、文字列連結が実行されます。
true + true // => 2ブール値は数に変換され、追加されます
2 + null // => 2 nullが0に変換され、追加します
2 +未定義// => NAN未定義の変換は追加のためにNANに変換されます
最後に、注意することが重要です。プラス記号操作が文字列に沿って使用される場合、操作の順序に対する追加の効果を考慮する必要があります。つまり、操作の結果は、たとえばオペレーターの操作順序によって異なります。
コードコピーは次のとおりです。
1 + 2 + "bmice" // => "3 bmice"
1 +(2 + "bmice")=> "12bmice"
ii。単一オペレーター
単一のオペレーターは、別のオペランドに作用します。新しい値を生成します。 JavaScriptでは、ユニールオペレーターは優先度が高く、すべての右に結合されています。このセクションでは、ユニリーオペレーター(+、 - 、++、および - )について説明し、必要に応じて操作を数値に変換します。 + - は単位オペレーターであり、バイナリ演算子でもあることに注意する必要があります。
1-yuan添加+
統一された追加オペレーターは、オペランド数を数値(またはNAN)に変換し、変換された数を返します。オペランド自体が数字の場合、数は直接返されます。
1-yuanの減算 -
- 記号が単位オペレーターの場合、必要に応じてオペランドを数値に変換し、操作結果のシンボルを変更します。
増分++
「++」演算子をインクリメントしてオペランドを増分(+1)し、オペランドはlvalue(可変、配列要素、またはオブジェクト属性)です。オペレーターは、オペランドを数値に変換します。次に、数に1を追加し、変数、配列要素、またはオブジェクト属性に1を追加した後、値を再割り当てします。
Increment ++操作は、オペランドの位置に依存する値を返します。
オペレーターがオペランド番号の前にいる場合、それは「プレインクリメント」演算子と呼ばれ、オペランドを徐々に計算し、計算された値を返します。
オペレーターがオペランドの後にいる場合、「ポストインクリメント」演算子と呼ばれます。オペランドで増分計算を実行しますが、インクリメンタル計算に使用される無制限の値を返します。のように
var i = 1、j = ++ i // iとjの値は両方です2
var i = 1、j = i ++; // iは2、jは1です
++ x = x+1の合計はまったく同じであることに注意してください。 「++」演算子は、文字列連結操作を実行することはありません。常にオペランドを数値に変換し、1だけ増加します。xが文字列「1」である場合、++ xの結果は数字2、x+1は文字列「11」です。
操作の減少と増分操作は同じであり、オペランドを配列に変換してから1で減算します。
iii。ビットオペレーター
ビット演算子は、数字で表されるバイナリデータに対して低レベルのビットワイズ操作を実行できます。それらは従来の純粋な数学的操作ではありませんが、数値タイプと返品数の操作に作用するため、ここでも算術演算子として分類されます。これらの演算子はJavaScriptでは一般的ではありません。 (ここでは説明していません。詳細についてはBaiduを使用してください〜-〜)
9。リレーショナル式
このセクションでは、JavaScriptの関係演算子について説明します。リレーショナル演算子は、2つの値(等式、「属性」未満または「属性」)間の関係をテストし、関係が存在するかどうかに応じてtrueとfalseを返すために使用されます。リレーショナル式は常にブール値を返し、通常、声明または声明(第5章)にリレーショナル式を使用して、プログラムの実行プロセスを制御します。
次のいくつかのセクションでは、平等と不均等な操作、比較演算子、およびJavaScriptの他の2つの関係文字について説明します。
I平等と不平等なオペレーター
「==」および「===」演算子は、2つの値が等しいかどうかを比較するために使用され、2つの演算子はあらゆるタイプの演算子を許可します。等しい場合はtrueを返し、それ以外の場合はfalseを返します。 「===」は、2つのオペランドが厳密に等しいかどうかを検出するために使用される、厳密な平等演算子(ID演算子とも呼ばれることもあります)とも呼ばれます。 「==」オペレーターは、等式演算子と呼ばれます。 2つのオペランドが等しいかどうかを検出するために使用されます。ここでの平等定義はゆるく、タイプ変換を可能にします。
JavaScriptは、「=」、「==」、「===」演算子をサポートしています。(割り当て、平等、アイデンティティ)オペレーターの違いを理解する必要があります。プログラミングするときは注意してください。混乱を減らすために、 "=" "は「get or assional」と呼ばれる必要があります。「=="は「等しい」と呼ばれ、「===」は「厳密に等しい」と呼ぶ必要があります。
「!=」と「!==」演算子のルールは「==」であり、「===」演算子の逆、および「!」です。ブールの非オペレーターです。 「!= "、"!== "と呼ばれ、厳密に等しくない。
JavaScriptオブジェクトの比較は、値の比較ではなく、参照の比較です。オブジェクトとそれ自体は等しいが、それらは人とオブジェクトに等しくない。 2つのオブジェクトに同じ数の属性、同じ属性名と値がある場合、それらはまだ不平等です。対応する位置の配列要素は等しく、2つの配列も等しくなります。
厳密な平等演算子「===」は、最初にオペランドの値を計算し、次にこれらの2つの値を比較します。比較プロセスに変換はありません。
2つの値のタイプが同じになりたくない場合、それらは等しくありません
両方の値がnullまたは未定義の場合、それらは等しくありません
両方の値がブールの真またはfalseである場合、それらは等しい
値の1つがNANである、または両方がNANである場合、それらは等しくなく、NANおよび他の値はそれ自体を含めて等しくありません。
2つの値が数字であり、等しい場合、それらは等しいです。値が0で、値が-0の場合、それらも等しくなります。
2つの値が文字列であり、対応するビットに含まれる16桁の数値(第3章、2を参照)が正確に等しい場合、それらは等しくなります。それらの長さまたはコンテンツが異なる場合、それらは等しくありません。 2つの文字列はまったく同じ関数であり、表示される文字は同じですが、エンコードされていない16ビット値があります。 JavaScriptはUnicodeで標準変換を実行しないため、「===」および「==」演算子と比較して、このような文字列は等しくありません。 string.localecompare()3番目の部分では、文字列を比較する別の方法を提供します。
2つの参照値が同じオブジェクト、配列、または関数を指している場合、それらは等しくなります。異なるオブジェクトを指す場合、それらは不平等ですが、2つのオブジェクトはまったく同じプロパティを持っています。
平等演算子「==」はID演算子に似ていますが、等式演算子は厳密に比較されません。 2つの数値が同じタイプでない場合、平等オペレーターはタイプ変換を行い、比較します。
2つの操作が同じ場合、上記の平等演算子の比較ルールは同じです。厳密に等しい場合、比較結果は等しくなります。それらが厳密に等しくない場合、比較結果は等しくありません。
2つの操作タイプが異なる場合、「==」等しい演算子もそれらを等しく見ています。平等の検出は、次のルールに従い、変換を型にします。
タイプが無効で、他のタイプを未定義にする場合、それらは等しくなります
1つの値が数字で、もう1つの値が文字列である場合、最初に文字列を数値に変換し、次に比較のために変換された値を使用します。
値が真の場合、それは1に変換されてから比較されます。値がfalseの場合、0に変換されて比較されます。
1つの値がオブジェクトであり、もう1つの値が数字または文字列である場合、第3章のメソッドの変換ルールを使用して、セクション8、3を使用してオブジェクトを元の値に変換し、それを比較します。オブジェクトは、toString()メソッドまたはvalueof()メソッドを介して元の値に変換されます。 JavaScript言語のコアにある組み込みクラスは、最初にValueof()を使用してから、toString()を使用しようとします。日付クラスに加えて、日付クラスはtoString()を介してのみ変換できます。 JavaScript言語のコアにないオブジェクトは、実装で定義されたメソッドを介して元の値に変換されます。
他のタイプ間の比較は等しくありません
これが平等な判断の小さな例です
「1」== true
この式の結果は真であり、完全に異なるタイプの値の比較結果が等しいことを示しています。ブール値は最初に番号1に変換され、次に比較が実行されます。次に、2つの数値の値が等しいため、文字列「1」も番号1に変換されるため、結果は真です。
ii。比較演算子
(<)未満
最初のオペランドが2番目のオペランドよりも小さい場合、「<」操作の結果は真です。
(<=)以下
(>)以上
(> =)以上
....(意味の詳細な紹介はありません)
比較演算子のオペランドは、あらゆるタイプのものである場合があります。ただし、数字と文字列のみが実際に比較演算子を実行できるため、数字と文字列ではないオペランドはタイプコンバージョンになります。タイプ変換ルールは次のとおりです。
オペランドがオブジェクトである場合、セクション3、セクション8、3で説明されている変換ルールに従って元の値に変換されます。valueof()がプリミティブ値を返す場合、この元の値を直接使用します。それ以外の場合は、比較のためにtoString()の変換結果を使用します。
元の値に変換した後、両方のオペランドが文字列である場合、2つの文字列をアルファベットの順に比較します。ここで説明した「アルファベット順」は、2つの文字列を構成する16ビットユニコード文字のインデックス順序です。
オブジェクトが元の値に変換された後、少なくとも1つのオペランドが文字列ではない場合、両方のオペランドが数字の値を比較します。 0と-0は等しい。 infintyの壁の他の数は大きい(infinty自体を除く)。オペランド(または変換された)がnanの場合、比較文字は常にfalseを返します
数値演算子と文字列演算子の場合、プラス記号演算子の動作は比較演算子とは異なります。前者は文字列を好み、そのオペランドの1つが文字列である場合、文字列連結操作を実行します。比較演算子は、両方のオペランドがひも文字列である場合にのみ数値を好みます。その場合にのみ、文字列の比較が実行されます。
コードコピーは次のとおりです。
1 + 2 // => 3追加、結果は3です
"1" + "2" // Connect String、結果は「12」です
「1」 + 2 //接続文字列、2は「2」に変換され、結果は「12」に変換されます
11 <3 //数の比較、結果は真です
"11" <"3" //スタンドの比較、結果は真です
"11" <3 //数字の比較 "11"は11に変換され、結果は真です
「1つ」<3 //番号の比較、「1つ」はNANに変換され、結果は偽です
最後に、平等を判断するとき、「<= "および"> = "オペレーターは平等演算子と厳格な平等操作の比較ルールに依存しないことに注意する必要があります。それどころか、オペレーターZHIは単に「より大きくない」ものであり、一方、操作以上の操作は「それ以下」だけです。 1つの例外のみを除いて、オペランド(変換後)がNANの場合、4つの比較演算子すべてがFasleを返します。
iii.inオペレーター
In Operatorは、左のオペランドが文字列であるか、文字列に変換できることを望んでおり、それが右側のオブジェクトであることを願っています。右側のオブジェクトに左オペランド値と呼ばれる属性名がある場合、式はtrueを返します。例えば
コードコピーは次のとおりです。
var point = {
X:1、
Y:1
} //オブジェクトを定義します
「x」のポイント// => trueオブジェクトにはxという名前のプロパティがあります
ポイントの「z」// => falseオブジェクトには名前z属性がありません
ポイントの「toString」// =>真のオブジェクトがtoStringメソッドを継承します
var data = [7、8、8]
データの「0」// => true配列に0が含まれます
1データ// => true convert numbersに文字列に変換します
データの3データ// => 3のインデックスを持つ要素なし
iiii.instance of operator
インスタンスのオペレーターは、左のオペレーターがオブジェクトであることを望んでおり、右オペランドはオブジェクトのクラスを示します。左側のオブジェクトが右側のクラスのインスタンスである場合、式はtrueを返します。偽りを返す責任があります。第9章で説明します。 JavaScriptオブジェクトのクラスは、コンストラクターを初期化することによって定義されます。このようにして、インスタンスの適切なオペランドは関数でなければなりません。例えば:
コードコピーは次のとおりです。
var d = new date(); //新しいオブジェクトを作成します
d日付のinstance; //計算の結果は真であり、Dは日付()によって作成されます
d instanceof Object //计算结果为true ,所有的对象都是Object的实例
d instanceof Number //计算结果为false,d不是一个Number对象
var a = [1,2,3] //数组直接量创建数组
a instanceof Array //计算结果true a为数组
a instanceof Object //true 所有的数组都是对象
a instanceof RegExp //fasle 数组不是正则表达式
需要注意的是,所有对象都是Object的实例。当通过instanceof盘对一个对象是否为一个类的实例的时候,这个判断也叫“父类”(superclass)的检测,如果instanceof的左侧操作对象不是对象的话,instanceof返回false。如果右侧操作不是函数,则抛出类型错误的异常。
为了理解instanceof运算符是如何工作的,必须首先理解“原型类”(prototype chain),原型链作为javascript的继承机制,将在6章2节2小节详细描述。
为了计算表达式o instanceof f ,javascript笔仙首先计算f.prototyoe,然后在原型链中查询o,如果找到,那么o是f(或者f的父类)的一个实例,那么返回true。反之false
10.逻辑表达式
逻辑运算符"&&"、“||”、“!”是对操作进行布尔算术运算,经常和关系运算符一起配合使用,逻辑运算符将多个关系表达式组合起来组成一个更复杂的表达式。
私。 Logic and
"&&"运算符可以从三个不同的层次进行理解。最简单一层理解是,当操作数都是布尔值是,“&&”对两个布尔值执行布尔与(AND)操作,只有在第一个操作数和第二个操作数都是true的时候,它才返回true.如果其中有一个操作数为false.则它返回false.
"&&"长用来连接两个关系表达式
x == 0 && y == 0; //只有在x和y都是0时,才返回true
关系表达式总是返回true或false,因此当这样使用的时候,“&&”本身也返回true或false。关系运算符的优先级要比"&&"(和“||”)要高,因此类似这种表达式可以放心地书写,而不用补充园括号。
"&&"操作数并不一定是布尔值,回想一下,有些值是可以当做“真值”和“假值”的。(如3章3节,假值是:false null undefined 0 -0 NaN和"",所有和其它的值包括所有的对象都是真值)。对“&&”第二层理解是,“&&”是可以对真值和假值进行布尔与(AND)操作。如果两个操作数都是真值的,则那么返回一个真值;否则,至少一个操作数是假值的。javascript中在任何使用布尔值的地方的时候,表达式语句都会将其当做真值或假值来对待,因此实际上“&&”并不总是返回true和false.但也并无大碍。
需要注意的是,上文提到了运算符返回“真值”和“假值”,但并没说说明这个“真值”或者“假值”到底是什么值,为此我们深入讨论对“&&”第三层的理解。运算符首先计算左操作数的值,即首先计算“&&”左侧的表达式,如果计算结果是假值,那么整个表达式的结果一定是假值,因此“&&”这时简单的返回左操作的值,而并不会对右边的操作数进行计算。
コードコピーは次のとおりです。
var o = {
x: 1
};
var p = null;
o && ox; //=>1 : 1:0是真值,因此返回值是ox
p && px //= null :p是假值,因此将其返回,而并不计算px
这对于理解“&&”可能不计算右操作数的情况至关重要,在上述代码中,变量P的值是null,而如果计算px的话则会抛出一个异常错误,因此,只有p为真值(不能是null或undefined)的情况下才计算px
"&&"的行为有时候被称为“短路”(short circuiting),我们经常能看到很多代码利用了这一也行来有条件的执行代码。例如下面的两条代码是等价的
コードコピーは次のとおりです。
if (a == b) stop(); //只有a==b时才能调运stop()
(a == b) && stop(); //同上
一般来讲,当“&&”右侧的表达式具有副作用的时候(赋值,递增,递减和函数调用表达式)要格外小心。因为这些带有副作用的表达式的执行时候,依赖于左操作鼠的计算结果。
尽管“&&”可以按照第二层和第三层的理解进行一些复杂的表达式运算,但大多数的情况下,“&&”仅用来对真值和假值的做布尔计算。
ii。 Logical or (||)
"||"运算符对两个操作数做布尔或(OR)运算。如果其中一个为真值,则返回真值,两个操作数都为假值,返回假值。
尽管“||”运算符大多情况下只是做简单的布尔或(OR)运算,和“&&”一样,也具备一些更复杂的行为,它首先计算第一个操作数的值,也就是说回首先计算左侧的表达式,如果计算结果为真,则返回真值,否则,再计算第二个值。
和“&&”一样,用于应该避免右操作数包含一些具有副作用的表达式,除非你目地明确在右侧使用带副作用的表达式,而有可能不会计算右侧的表达式。
这个运算符最常用的方式是用来从一组备选的表达中选取第一个真值的表达式。
コードコピーは次のとおりです。
//如果max_width已经定义了,则直接使用它。赋值在preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量。
var max =max_width || preferences.max_windth || 500;
这种贯用法通常在函数体内,用来给参数提供默认值。
コードコピーは次のとおりです。
//将o成功的属性复制到p中,并返回p
function copy(o, p) {
p = p || {}; //If no object is passed into the parameter p, a newly created object is used.
//函数体内的主逻辑
iii.逻辑非(!)
"!"运算符是一元运算符,它放置在一个单独操作数之前。它的目的是将操作数的布尔值求反。
和"&&"、"||"运算符不同,“!”运算符首先将其操作数转换为布尔值(参考第三章的讲诉规则),然后再对布尔值求反。也就是"!"总是返回true和false。并且,可以通过使用两次逻辑非运算来得到一个值的布尔值:(!!x,参照第三章第八节第2小节)
“!”具有很高的优先级,并且和操作数紧密的绑在一起,如果希望对p && q,则需要园括号!(p && q)。如下代码:
コードコピーは次のとおりです。
!(p && q) === !p || !q
!(p || q) === !p && !q
对于p和q取任何值,这两个表达式永远成立。
11.赋值表达式
javascript使用"="运算符给变量或者属性来赋值,例如:
コードコピーは次のとおりです。
i = 0 //将变量i设置为0
ox = 1 //将对象o的属性x 设置为1
“=”运算符希望它的左操作数为一个左值:一个变量或者对象属性(或数组元素),它的右操作鼠可以是任意的类型的任意值。赋值表达式的值就是右操作数的值。赋值表达式的副作用是,右操作数的值赋值给左侧的变量或对象属性。这样的话,后续对这个变量和对象的属性的引用都将得到这个值。
尽管赋值表达式的值非常简单,但有时候会看到一些复杂表达式包含赋值表达式的情况。例如:将赋值和检测操作放在一个表达式中:
コードコピーは次のとおりです。
(a = b) == 0
如果这样的话,应该清楚地知道"="和"=="区别!,需要注意的是,“=”有非常低的优先级,通常在一个较长的表达式中用到一条赋值语句时,需要补充园括号以保障正确的运算顺序。
赋值操作符的结合性是从右至左,也就是说,一个表达式中出现了多个赋值运算符,运算顺序也从右至左,因此,可以通过以下方式对多个变量赋值。
コードコピーは次のとおりです。
i=j=k=0; //把三个变量初始化为0
带操作的赋值运算:
除了常规的赋值运算外,javascript还支持需要其他的赋值运算符,这些运算符将赋值运算符合其他的运算符连接起来。提供一种更为快捷的运算方式。例如+=运算符执行的是加法运算符和赋值操作,下面的表达式:
total += salaes_tax;
和下面的表达式等价的
total = total + salaes_tax
运算符“+=”可以作用于数字或字符串,如果其操作是数字,它将执行加法运算和赋值操作;如果是字符串,他就执行字符串的连接和赋值操作。
此类型的运算符还包括,"-=","*=","&="等,如下表赋值运算符
运算符示例等价于
+=a+=ba=a+b
-=a-=ba=ab
*=a*=ba=a*b
/=a/=ba=a/b
%=a%=ba=a%b
<<=a<<=ba=a<<b
>>=a>>=ba=a>>b
>>>=a>>>=ba=a>>>b
&=a&=ba=a&b
|=a|=ba=a|b
^=a^=ba=a^b
大多数情况下,表达式为
a op =b
这里的op代表一个运算符,这个表达式等价于
a =a op b
在第一行中,表达式a计算了一次,在第二行中,表达式a计算了两次。
只有a包含具有副作用的表达式(比如函数调用和赋值操作)的时候,两者才不等价。如下两个表达式不等价
コードコピーは次のとおりです。
data[i++] *= 2;
data[i++] = data[i++] * 2
12.表达式计算
和很多解释性语言一样,javascript同样可以解释运行由javascript源代码组成的字符串,并产生一个值。javascript通过全局函数eval()来完成这个工作。
eval("3+2") //=>5
动态判断源代码中的字符串是一种强大语言的特性,几乎没有必要在实际中应用。如果你使用了eval(),你应该仔细考虑真的需要它。
下面降价eval()基础用法,并介绍两种严格使用它的方法,从代码优化的角度来讲,这两种方法对原有的代码影响是最小的。
i.eval (eval()是一个函数,但由于它已经被当做运算符来对待了。)
eval()只有一个参数,如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成javascript进行编译(parse),如果编译失败则抛出一个语法错误(SyntaxError)。如果编译成功,则开始执行这段代码,并返回字符串中最后一个表达式或语句的值,如果最后一个表达式没有语句或者值,则最终返回undefined。如果字符串抛出一个异常,这个异常把该调用的传给eval()
关于eveal()最重要的是,它使用了调用它的变量作用域环境,也就是说,它查找变量的值和定义新变量和函数的操作和局部的代码作用域中的代码一样。如果一个函数定义了一个局部变量x,然后调用了eval("x"),它会返回局部变量的值。如果它调用eval("x=1"),它会改变局部变量的值。如果函数调用了eval("var y=3;")它声明一个新的局部变量y。同样的,一个函数可以通过如下代码声明一个局部函数:
eval("function f(){return x+1;}");
如果最顶层的代码中调用了eval()。当然它会作用于全局变量和全局函数。
ii。 Global eval()
eval()具有改变局部变量的能力,这对javascript优化器来说,是一个很大的问题,然而作为一种权宜之计,javascript征对那行调用了eval()函数所做的优化并不多。但当脚本定义了一个别名,并且用令一个名称来调用它,javascript解释器又如何工作呢,为了javascript解释器更加简化。ECMAScipt3标准规定了任何解释器都不允许对eval()赋予别名。如果eval()使用别的别名来调用的话,则会抛出EvalError异常。
实际上,大多数的实现并不是这样做的。当通过别名调用时,eval()会将其字符串当成顶层的全局代码来执行。执行代码可能会定义新的全局变量和全局函数。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值。但却不能修改或修改主调函数中的局部变量,因此这不会影响到函数内的代码优化。
ECMAScript5是反对使用EvalError的,并且规范了eval()的行为。“直接的eval”,当直接使用非限定的“eval”名称,来调用eval()函数时,它总共是在它的上下文作用域内支线。其它间接调用则使用全局函数为其上下文作用域。并且无法读、写、定义局部变量和函数。下面有一段代码实例:
コードコピーは次のとおりです。
var geval = eval; //使用别名调用eval将是全局eval
var x = "global",
y = "global"; //两个全局变量
function f() { //函数内执行的局部eval
var x = "local" //定于局部变量
eval("x += 'changed';"); //直接eval更改了局部变量的
xを返します。 //Return the changed local variable
}
function g() { //这个函数执行了全局eval
var y = "local" //定义了局部变量
geval("y += 'changed';"); //间接改变了局部变量的值
return y; //返回未更改的局部变量
}
console.log(f(), x); //更改了局部变量,输出local changed global
console.log(g(), y); //更改了全局变量,输出local globalchanged
13.其它运算符。
javascript支持很多其它各种各样的运算符。
私。 Conditional operator (?:)
The conditional operator is the only ternary operator in javascript. Usually this operator is written as "?:". This operator has the third operand, the first operand is before "?", and the second operand is between "?"そして ":"。 The third operand is long after ":", e.g.
x > 0 ? x : -x; //求x的绝对值
条件运算符的操作数可以是任意类型。第一个操作数当成布尔值,如果它是真值,那么将计算第二个操作数,并返回计算结果。赋值如果第一个值操作数是假值,那么将计算第三个操作数。并返回计算结果。第二个和第三个操作数总会计算其中之一。不可能两者同时进行。其实使用if语句也达到同样的效果(5.4.1),“?:”运算符只是提供了一种简写形式。这里是一个"?:"的典型使用场景,判断一个变量是否有定义,如果有定义则使用它,如果无定义,则使用一个默认值。
コードコピーは次のとおりです。
grett = "hello" + (username ? username : "three");
和以下的代码是等价的,但上面的更加简洁
コードコピーは次のとおりです。
grett = "hello";
if (username)
grett += username;
それ以外
grett + "three"
ii.typeof()运算符
typeof是一元运算符,放在单个操作数前面,操作数可以是任何类型,返回值表示操作类型的一个字符串。
コードコピーは次のとおりです。
x __ typeof x
undefined __ "undefined"
null __ "object"
ture或false __"boolean"
任意数字或NaN __ "Number"
任意字符串__ "String"
任意函数__ "function"
任意内容对象(非函数)__ "object"
任意宿主对象__ 由编译器各自实现的字符串,但不是"undefined" "boolean" "number" "string"
typeof最常用的用法写在表达式中们就像这样
(typeof value == "string") ? "" + value + "":value;
typeof运算符同样在swith语句中(5.4.3)非常有用,需要注意的是,typeof运算可以带上园括号。这样让typeof看起来像一个函数名,而非关键字
typeof(i)
iii.delete运算符
delete是一元操作符,它用来删除对象的属性或者数组的元素。就像赋值、递增、递减运算符一样。delete也是具有副作用的。它是用来做删除操作的。不是用来返回一个值的。
コードコピーは次のとおりです。
var o = {
x: 1,
y: 2
}
delete ox;
"x" in o; //=>false
var a = [1, 2, 3];
delete a[2]; // 删除数组中最后一个元素
2 in a; //=> false 元素2已经在数组中不存在了
a.length; //=>3,注意,数组长度并没有改变,尽管上一行删除了这个元素,但删除操作留下了一个洞。实际上并没有修改数组的长度,因此a的长度仍然为3
需要注意的是,删除属性或删除数组元素不仅仅设置了一个undefined值,当删除一个属性时,这个属性不复存在。读取一个不存在的值将会返回undefined.关于delete删除还有严格模式下的一些情况,需要学习的人自己试验,这里给一些例子。
コードコピーは次のとおりです。
var o = {x: 1,y: 2};
delete ox; //删除一个对象属性,返回true
typeof ox; //属性不存在,返回"undefined"
delete ox; //删除不存在的属性,返回true;
delete o; //不能删除通过var关键字声明的变量,返回false
delete 1; //参数不是一个左值。
this.x = 1;// 给全局定义一个属性,这里没有使用var
delete x ; //试图删除它,在非严格模式下返回true
//在严格模式下回抛出异常,这时使用"delete this.x"来代替
x; //运行时出错,没有定义x
6章第三节还有关于delete的讨论。
iii.void运算符。
void是一元运算符,在出现操作数之前,操作数可以是任何类型。这个运算符并不是经常使用:操作数会照常计算,但会忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用时使用void来程序更有意义。
这个最常用的带客户端url.在url写带有副作用的表达式,而void则让浏览器不显示在这个表达式的运算结果。
コードコピーは次のとおりです。
<a href="javascript:void window.open();">new</a>
iiii.逗号运算符。(,)
逗号运算符是二元运算符,它的操作数可以是任意类型。它首先计算左操作数,然后计算右操作数。
コードコピーは次のとおりです。
i = 0, j = 1, k = 2;
它和下面的代码基本上等价的
i = 0; j = 1; k = 2;
总是会计算左侧的表达式,但计算结果忽略掉,也就是说,只有左侧表达式具有副作用,才会使用逗号运算让代码变得更通畅。逗号运算符最常用的场景是for循环中,这个for循环通常有多个循环变量。
コードコピーは次のとおりです。
//for循环中的第一个逗号是var语句的一部分
//第二个逗号是逗号运算符
//它将两个表达式(i++和j++)放在一条(for循环中)语句中
for (var i = 0, j = 10; i < j; i++, j--);
console.log(i + j);