コアポイント
if
またはfor
ブロックで宣言された変数が関数またはグローバルスコープに宣伝されています。 with
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
scope with
ほとんどの開発者は、JavaScriptを使用し始めます。なぜなら、彼らはそうすることを余儀なくされているため、ほとんどすべての開発者が言語の学習に時間を費やす前にコードを書き始めます。そのような開発者はそれぞれ、JavaScriptの範囲に少なくとも一度はだまされています。 JavaScriptの構文はCシリーズの構文と非常によく似ているため(意図的に)、機能の本体を分離します。ブレースでは、字句ブロックレベル範囲を合理的に期待するでしょう。残念ながら、そうではありません。まず、JavaScriptでは、可変スコープは、ブラケットではなく関数によって決定されます。言い換えれば、身体が新しいスコープを作成しない場合、および体内で宣言された変数が実際に促進されます。つまり、それを宣言する最も内側の関数の先頭に作成されます。第二に、with
ステートメントの存在により、JavaScriptの範囲は動的になり、実行時まで決定することはできません。 with
ステートメントの使用が非推奨されていることを聞いて驚かないかもしれません。with
のないJavaScriptは、実際には語彙的なスコープ言語になります。つまり、コードを見ることで範囲を完全に決定できます。 JavaScriptには、スコープに入るには4つの方法があります。-言語定義:デフォルトでは、すべてのスコープには名前this
およびarguments
が含まれています。 - 正式なパラメーター:関数に対して宣言された(正式な)パラメーターの範囲は、関数の本体に属します。 - 関数宣言。 - 変数宣言。
別の複雑さは、(暗黙的に)var
キーワードで宣言されていない(暗黙的に)変数割り当ての暗黙のグローバル範囲によって引き起こされます。この狂気は、明示的なバインディングなしで関数を呼び出すときのグローバルスコープの暗黙の割り当てと組み合わされます(次のセクションでは詳細)。詳細を掘り下げる前に、混乱を避けるためにどのような良いパターンを使用できるかを明確にしましょう内部およびそれらのブロックの場合、およびそれらのブロック内の関数の宣言(これは、さまざまな理由でこの記事の範囲を超えています)。 this
標高
'use strict';
標高は、ステートメントの実際の動作を説明するための単純化された方法です。宣伝された変数は、含まれている関数の先頭に宣言され、
コンソールに印刷すると予想される値は何ですか?次の出力に驚かないでしょうか? undefined
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
ブロックでは、if
ステートメントは変数のローカルコピーを宣言するのではなく、以前に宣言された変数を上書きします。最初のvar
ステートメントは、変数i
の実際の値を印刷します。関数の最初の行としてconsole.log
ディレクティブを使用してテストできます。厳密なモードでは、使用する前に変数を宣言する必要がありますが、JavaScriptエンジンが宣言のためにエラーを報告しないことを確認できます。ちなみに、i
の再征服のためにエラーを報告しないことに注意してください:そのようなエラーをキャッチしたい場合は、JshintやJSlintなどのリナーを使用してコードを処理することをお勧めします。それでは、別の例を見て、変数宣言の別のエラーが発生しやすい使用法を強調しましょう。
undefined
"use strict";
違うことを期待するかもしれませんが、var
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
によって宣言されているため、if
本体は実行されます。ここでも必須の作品を入力してください。 test()
notNull
関数宣言と関数式
標高は変数に適用されるだけでなく、関数式式
これを次の例と比較して、関数式の式の動作を示します。 これらの概念をさらに理解するには、参照セクションを参照してください。 with
<code>undefined 0 5 5</code>
var notNull = 1; function test() { if (!notNull) { console.log("Null-ish, so far", notNull); for(var notNull = 10; notNull < 20; notNull++) { //.. } console.log("Now it's not null", notNull); } console.log(notNull); }
という名前のフィールドがある場合、関数
は楽しみにしています:ecmascript 6
function foo() { // 函数声明 function bar() { return 3; } return bar(); // 此函数声明将被提升并覆盖之前的声明 function bar() { return 8; } }
ecmascript 6仕様は、ブロックレベルのスコープ:y
ステートメントを追加する5番目の方法を追加します。次のコードを検討してください:x
foo()
ECMaScript 6では、y.x
宣言の本体の内部を使用して、with
ブロックの新しい可変ローカルを作成します。標準以外の代替品として、
let
スコープの概要
function foo() { // 函数表达式 var bar = function() { return 3; }; return bar(); // 变量 bar 已经存在,并且永远不会到达此代码 var bar = function() { return 8; }; }
特性 | Java | Python | JavaScript | 警告 |
---|---|---|---|---|
作用域 | 词法(块) | 词法(函数、类或模块) | 是 | 它与 Java 或 C 的工作方式大相径庭 |
块作用域 | 是 | 否 | let 关键字(ES6) |
再一次警告:这不是 Java! |
提升 | 不可能! | 否 | 是 | 仅提升变量和函数表达式的声明。对于函数声明,也会提升定义 |
函数 | 作为内置类型 | 是 | 是 | 回调/命令模式对象(或 Java 8 的 lambda) |
动态创建 | 否 | 否 | eval – Function 对象 |
eval 存在安全问题,Function 对象可能无法按预期工作 |
属性 | 否 | 否 | 可以具有属性 | 无法限制对函数属性的访问 |
闭包 | 弱化,只读,在匿名内部类中 | 弱化,只读,在嵌套的 def 中 | 是 | 内存泄漏 |
function
JavaScriptのもう1つの非常に誤解されている機能は、特にJavaなどの命令的なプログラミング言語で機能する機能が機能しないことです。機能の概念はありません。実際、JavaScriptは機能的なプログラミング言語です。まあ、それはHaskellのような純粋な機能的プログラミング言語ではありません - 結局のところ、それはまだ命令的なスタイルを持っています、そして、Scalaのように単に許可するのではなく、変動を促進します。ただし、JavaScriptは純粋に機能的なプログラミング言語として使用でき、副作用のない関数呼び出しを使用できます。
オブジェクト
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
関数コンストラクターを使用すると効率が悪く、匿名の関数が生成され、作成コンテキストの閉鎖が作成されないため、ほぼ同等であると言います。関数オブジェクトは、常にグローバル範囲で作成されます。関数(関数のタイプ)はオブジェクト上に構築されます。これは、宣言する機能をチェックすることで簡単に確認できます。
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
これは、関数にプロパティが可能であることを意味します。これらのいくつかは、名前や長さなど、作成時に関数に割り当てられています。これらのプロパティは、それぞれ関数定義の名前とパラメーターの数を返します。次の例を考えてみましょう:
<code>undefined 0 5 5</code>
しかし、自分で機能の新しいプロパティを設定することもできます:
var notNull = 1; function test() { if (!notNull) { console.log("Null-ish, so far", notNull); for(var notNull = 10; notNull < 20; notNull++) { //.. } console.log("Now it's not null", notNull); } console.log(notNull); }
関数の概要
function foo() { // 函数声明 function bar() { return 3; } return bar(); // 此函数声明将被提升并覆盖之前的声明 function bar() { return 8; } }
クロージング
お気に入りのJavaScript機能を選択するように求められた場合、ためらうことなく閉鎖を選択します。 JavaScriptは、閉鎖を導入する最初の主流プログラミング言語です。ご存知のように、JavaとPythonは長い間、閉鎖されたスコープの値を読むことができる閉鎖のバージョンを弱体化させてきました。たとえば、Javaでは、匿名の内部クラスが閉鎖のような機能を提供し、特定の制限を提供します。たとえば、最終的なローカル変数はその範囲でのみ使用できます。より正確には、それらの値を読むことができます。 JavaScriptを使用すると、外部スコープ変数と関数に完全にアクセスできます。必要に応じて、ローカルの定義によって読み、書かれ、さらには隠されています。これらすべてのケースの例をスコープセクションで見ることができます。さらに興味深いのは、閉鎖で作成された関数が、それが作成された環境を覚えていることです。閉鎖と機能のネストを組み合わせることにより、外部関数を実行せずに内部関数を返すことができます。さらに、外部関数のローカル変数を、それらを宣言する関数の実行が終了した場合でも、内部関数の閉鎖において長持ちすることができます。これは非常に強力な機能ですが、JavaScriptアプリケーションのメモリリークの一般的な原因であるため、その欠点もあります。いくつかの例では、これらの概念を説明します:
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
上記のmakeCounter()
関数は、作成した環境を追跡する別の関数を作成して返します。変数の実行は、変数が割り当てられたときに終了しますが、ローカル変数counter
はmakeCounter()
の閉鎖に残るため、その体内でアクセスできます。再び実行したい場合は、i
のエントリが異なる新しい閉鎖が作成されます。
displayCounter
makeCounter
より興味深いものにするために、パラメーターを受け入れるようにi
関数を更新できます:
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
外部関数パラメーターも閉鎖に保存されるため、今回はローカル変数を宣言する必要はありません。各呼び出しmakeCounter()
は、設定した初期値を覚えており、カウントを継続します。閉鎖は、多くの基本的なJavaScriptパターンに不可欠です:名前空間、モジュール、プライベート変数、メモリは最も有名です。たとえば、オブジェクトのプライベート変数をシミュレートする方法を見てみましょう。
<code>undefined 0 5 5</code>
閉じる概要makeCounter()
特性 | Java | Python | JavaScript | 警告 |
---|---|---|---|---|
闭包 | 弱化,只读,在匿名内部类中 | 弱化,只读,在嵌套的 def 中 | 是 | 内存泄漏 |
记忆化模式 | 必须使用共享对象 | 可以使用列表或字典 | 是 | 最好使用惰性求值 |
命名空间/模块模式 | 不需要 | 不需要 | 是 | |
私有属性模式 | 不需要 | 不可能 | 是 | 可能令人困惑 |
結論
この記事では、さまざまな言語、特にJavaとC.の開発者によって誤解されることが多いJavaScriptの3つの機能を紹介します。特に、範囲、プロモーション、機能、閉鎖などの概念について説明します。これらのトピックを掘り下げたい場合は、読むことができるいくつかの記事のリストを次に示します。 JavaScript機能(FAQ)に関するlet
JavaScriptの「==」と「===」の違いは何ですか? let
JavaScriptでは、「==」と「===」は比較演算子ですが、それらは異なって動作します。 「==」オペレーターは、loose平等演算子と呼ばれます。必要なタイプ変換を実行した後、2つの値が等しいかどうかを比較します。これは、数値を文字列と数値リテラルと比較すると、trueを返すことを意味します。たとえば、「5」== 5がtrueを返します。一方、「===」は厳格な平等オペレーターです。タイプ変換は実行されないため、2つの値タイプが異なる場合、falseを返します。たとえば、「5」=== 5は、1つが文字列であり、もう1つは数字であるため、Falseを返します。
JavaScriptの改善は何ですか?
javascriptのグローバル変数とローカル変数の違いは何ですか?
JavaScriptの「この」キーワードは何ですか?
JavaScriptの閉鎖は、外部関数の独自の範囲、範囲、グローバル範囲、およびアクセス関数パラメーターと変数にアクセスできる関数です。これにより、関数が返された外部関数内の変数にアクセスし、変数をメモリ内に保ち、データプライバシーと関数工場を許可します。
javascriptでは、関数は多くの方法で定義できます。そのうちの2つは関数宣言と関数式です。関数宣言は指定された関数を定義し、宣言が促進され、それを定義する前に関数を使用できるようにします。関数式は、式の関数を定義し、宣伝されていません。つまり、定義前には使用できません。
「let」、「var」、および「const」はすべて、JavaScriptの変数を宣言するために使用されますが、スコープルールが異なります。 「var」は関数スコープされています。つまり、宣言する関数内でのみ使用できます。 「let」と「const」はブロックスコープされています。つまり、宣言するブロック内でのみ使用できます。 「let」と「const」の違いは、「let」を使用すると変数を再割り当てできることですが、「const」は変数を再割り当てしません。
JavaScriptでは、オブジェクトと配列がデータを保存するために使用されますが、それらはさまざまな方法で保存されます。オブジェクトはプロパティのコレクションであり、各プロパティはキー価値ペアです。キーは文字列であり、値は任意のデータ型です。配列は、アイテムのリストを表す特別なタイプのオブジェクトです。キーは数値インデックスであり、値は任意のデータ型にすることができます。
JavaScriptでは、関数は特定のタスクを実行するように設計されたコードのブロックであり、必要に応じて使用できる別のエンティティです。一方、メソッドはオブジェクトに関連付けられた関数、つまり、メソッドは関数としてオブジェクトのプロパティです。メソッドは、オブジェクトの属性として値を割り当てる必要があることを除いて、通常の関数と同じ方法で定義されます。
以上がJava/C開発者が知っておくべき3つのJavaScriptの癖の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。