ホームページ > ウェブフロントエンド > jsチュートリアル > Java/C開発者が知っておくべき3つのJavaScriptの癖

Java/C開発者が知っておくべき3つのJavaScriptの癖

Lisa Kudrow
リリース: 2025-02-20 10:28:12
オリジナル
709 人が閲覧しました

Three JavaScript Quirks That Java/C Developers Should Know

コアポイント

  • cまたはjavaとは異なり、JavaScriptのスコープは、ifまたはforブロックで宣言された変数が関数またはグローバルスコープに宣伝されています。
  • JavaScriptの高度は、変数と関数宣言がコンパイル中に含まれるスコープの上部に移動することを意味しますが、初期化は上昇していません。
  • JavaScriptの関数は、一流の市民として扱われます。つまり、変数に保存され、パラメーターとして渡され、他の機能によって返され、オブジェクトのようなプロパティがあることを意味します。
  • JavaScriptの
  • ステートメント(動的スコープ変数)は、ランタイムエラーを引き起こし、本質的に混乱を招く可能性があるため非推奨されています。
  • JavaScriptはクロージャーをサポートし、関数が返品後に外部関数の変数にアクセスできるようにし、それによりデータプライバシーを強化し、モジュールやプライベート変数などの強力なプログラミングモードを有効にします。 with
  • javascriptは欺cept的な言語である可能性があります。100%一貫していないため、痛みを伴う可能性があります。
、つまり避けるべき混乱または冗長な機能のいくつかの悪い部分があることが知られています:悪名高い声明、暗黙のグローバル変数、および比較行動の例外はおそらく最も有名です。 JavaScriptは、歴史上最も成功した火炎ジェネレーターの1つです!欠陥とは別に(新しいECMAScript仕様で部分的に解決された)、ほとんどのプログラマーは2つの理由でJavaScriptを嫌います。 - 彼らはCや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;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
これが、通常、JavaScriptがそれに値するよりも悪い評判を持っている理由です。私のキャリアでは、いくつかのパターンに気づきました。JavaまたはC/Cの背景を持つほとんどの開発者は、JavaScriptで同じ言語機能を考えており、それらは完全に異なっています。この記事では、最も厄介な言語機能を収集し、JavaアプローチをJavaScriptアプローチと比較して違いを示し、JavaScriptのベストプラクティスを強調しています。

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);
}
ログイン後にコピー
ログイン後にコピー

という名前のフィールドがある場合、関数

に戻り、それ以外の場合は123が返されます。このコーディングの練習は、ランタイムエラーの原因である可能性があるため、

ステートメントを避けることを強くお勧めします。

楽しみにしています: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)
动态创建 evalFunction 对象 eval 存在安全问题,Function 对象可能无法按预期工作
属性 可以具有属性 无法限制对函数属性的访问
闭包 弱化,只读,在匿名内部类中 弱化,只读,在嵌套的 def 中 内存泄漏

function

JavaScriptのもう1つの非常に誤解されている機能は、特にJavaなどの命令的なプログラミング言語で機能する機能が機能しないことです。機能の概念はありません。実際、JavaScriptは機能的なプログラミング言語です。まあ、それはHaskellのような純粋な機能的プログラミング言語ではありません - 結局のところ、それはまだ命令的なスタイルを持っています、そして、Scalaのように単に許可するのではなく、変動を促進します。ただし、JavaScriptは純粋に機能的なプログラミング言語として使用でき、副作用のない関数呼び出しを使用できます。

ファーストクラスの市民

JavaScriptの関数は、文字列や数値など、他のタイプと同じように扱うことができます。変数に保存し、関数にパラメーターとして渡され、関数によって返され、配列に保存されます。関数はプロパティを持つこともでき、...

オブジェクト

ほとんどの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;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
これは、次のようにほぼ同等です

関数コンストラクターを使用すると効率が悪く、匿名の関数が生成され、作成コンテキストの閉鎖が作成されないため、ほぼ同等であると言います。関数オブジェクトは、常にグローバル範囲で作成されます。関数(関数のタイプ)はオブジェクト上に構築されます。これは、宣言する機能をチェックすることで簡単に確認できます。
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;
    }
}
ログイン後にコピー
ログイン後にコピー
次の表には、Java、Python、およびJavaScriptの関数について説明します。

クロージング

お気に入りの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()関数は、作成した環境を追跡する別の関数を作成して返します。変数の実行は、変数が割り当てられたときに終了しますが、ローカル変数countermakeCounter()の閉鎖に残るため、その体内でアクセスできます。再び実行したい場合は、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パターンに不可欠です:名前空間、モジュール、プライベート変数、メモリは最も有名です。たとえば、オブジェクトのプライベート変数をシミュレートする方法を見てみましょう。

このパターンを使用して、閉鎖を使用して、プロパティ名のラッパーを作成し、独自のセッターとゲッターを使用できます。 ES5は、ゲッターとセッターを使用してプロパティ用のオブジェクトを作成し、最高級の穀物自体へのプロパティ自体へのアクセスを制御できるため、これをはるかに簡単にします。
<code>undefined
0
5
5</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

閉じる概要makeCounter()

次の表では、Java、Python、およびJavaScriptの閉鎖について説明しています。
特性 Java Python JavaScript 警告
闭包 弱化,只读,在匿名内部类中 弱化,只读,在嵌套的 def 中 内存泄漏
记忆化模式 必须使用共享对象 可以使用列表或字典 最好使用惰性求值
命名空间/模块模式 不需要 不需要
私有属性模式 不需要 不可能 可能令人困惑

結論

この記事では、さまざまな言語、特にJavaとC.の開発者によって誤解されることが多いJavaScriptの3つの機能を紹介します。特に、範囲、プロモーション、機能、閉鎖などの概念について説明します。これらのトピックを掘り下げたい場合は、読むことができるいくつかの記事のリストを次に示します。 JavaScript機能(FAQ)

に関する FAQ let JavaScriptの「==」と「===」の違いは何ですか? let JavaScriptでは、「==」と「===」は比較演算子ですが、それらは異なって動作します。 「==」オペレーターは、loose平等演算子と呼ばれます。必要なタイプ変換を実行した後、2つの値が等しいかどうかを比較します。これは、数値を文字列と数値リテラルと比較すると、trueを返すことを意味します。たとえば、「5」== 5がtrueを返します。一方、「===」は厳格な平等オペレーターです。タイプ変換は実行されないため、2つの値タイプが異なる場合、falseを返します。たとえば、「5」=== 5は、1つが文字列であり、もう1つは数字であるため、Falseを返します。

なぜJavaScriptはnullと未定義の両方を持っているのですか?

JavaScriptでは、nullと未定義は存在しない特別な値です。ただし、それらはわずかに異なって使用されます。未定義とは、変数が宣言されているが、まだ割り当てられていないことを意味します。一方、Nullは割り当て値であり、値もオブジェクトもないことを示します。変数の値が存在しないことを意味しますが、未定義とは変数自体が存在しないことを意味します。

JavaScriptの改善は何ですか?

標高は、コンパイルフェーズ中に変数と関数宣言を含む範囲の上部に移動するJavaScriptのメカニズムです。これは、変数を宣言する前に変数と関数を使用できることを意味します。ただし、宣言のみが促進され、初期化は促進されないことに注意する必要があります。変数が使用後に宣言および初期化された場合、値は未定義になります。

javascriptのグローバル変数とローカル変数の違いは何ですか?

javascriptでは、変数はグローバル変数またはローカル変数にすることができます。グローバル変数は、関数の外側で宣言された変数、または「var」キーワードで宣言された変数です。スクリプト内の任意の関数からアクセスできます。一方、ローカル変数は、「var」キーワードを使用して関数内で宣言された変数です。宣言する関数内でのみアクセスできます。

JavaScriptの「この」キーワードは何ですか?

JavaScriptの「この」キーワードは特別なキーワードであり、関数を呼び出すというコンテキストを指します。その値は、関数がどのように呼び出されるかに依存します。方法では、「This」は所有者オブジェクトを指します。個別に、「この」はグローバルオブジェクトを指します。関数では、「This」はグローバルオブジェクトを指します。イベントでは、「This」とは、イベントを受け取る要素を指します。

JavaScriptの閉鎖は何ですか?

JavaScriptの閉鎖は、外部関数の独自の範囲、範囲、グローバル範囲、およびアクセス関数パラメーターと変数にアクセスできる関数です。これにより、関数が返された外部関数内の変数にアクセスし、変数をメモリ内に保ち、データプライバシーと関数工場を許可します。

JavaScriptの関数宣言と関数式の式の違いは何ですか?

javascriptでは、関数は多くの方法で定義できます。そのうちの2つは関数宣言と関数式です。関数宣言は指定された関数を定義し、宣言が促進され、それを定義する前に関数を使用できるようにします。関数式は、式の関数を定義し、宣伝されていません。つまり、定義前には使用できません。

javascriptの「let」、「var」、「const」の違いは何ですか?

「let」、「var」、および「const」はすべて、JavaScriptの変数を宣言するために使用されますが、スコープルールが異なります。 「var」は関数スコープされています。つまり、宣言する関数内でのみ使用できます。 「let」と「const」はブロックスコープされています。つまり、宣言するブロック内でのみ使用できます。 「let」と「const」の違いは、「let」を使用すると変数を再割り当てできることですが、「const」は変数を再割り当てしません。

JavaScriptのオブジェクトと配列の違いは何ですか?

JavaScriptでは、オブジェクトと配列がデータを保存するために使用されますが、それらはさまざまな方法で保存されます。オブジェクトはプロパティのコレクションであり、各プロパティはキー価値ペアです。キーは文字列であり、値は任意のデータ型です。配列は、アイテムのリストを表す特別なタイプのオブジェクトです。キーは数値インデックスであり、値は任意のデータ型にすることができます。

JavaScriptのメソッドと機能の違いは何ですか?

JavaScriptでは、関数は特定のタスクを実行するように設計されたコードのブロックであり、必要に応じて使用できる別のエンティティです。一方、メソッドはオブジェクトに関連付けられた関数、つまり、メソッドは関数としてオブジェクトのプロパティです。メソッドは、オブジェクトの属性として値を割り当てる必要があることを除いて、通常の関数と同じ方法で定義されます。

以上がJava/C開発者が知っておくべき3つのJavaScriptの癖の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート