検索
ホームページウェブフロントエンドjsチュートリアルme_javascript スキルから JScript のバグとメモリ管理を学ぶ

1. JScript のバグ

IE の JScript の ECMAScript 実装は、名前付き関数式に深刻な混乱をもたらし、多くの人が名前付き関数式に反対しており、現在も使用されているバージョン (IE8 で使用されているバージョン 5.8) さえも存在しています。次のような質問があります。

IE が実装時に犯した間違いを見てみましょう。よく言われるように、敵を知ることによってのみ無敵になれます。次の例を見てみましょう:

例 1: 外部スコープに漏洩した関数式の識別子

var f = function g(){};
typeof g; // "function"

名前付き関数式の識別子は外部スコープでは無効であると前述しましたが、JScript は明らかにこの仕様に違反しています。上記の例の識別子 g は関数オブジェクトに解析されますが、これは非常に複雑です。 -to-find バグはこの理由によって発生します。

注: この問題は IE9 で修正されたようです

例 2: 名前付き関数式を関数宣言と関数式の両方として扱います

typeof g; // "function"
var f = function g(){};

フィーチャー環境では、関数宣言は式の前に解析されます。上記の例は、JScript が実際の宣言の前に g を解析するため、名前付き関数式を実際に関数宣言として扱うことを示しています。

この例は次の例につながります。

例 3: 名前付き関数式は、2 つのまったく異なる関数オブジェクトを作成します。

var f = function g(){};
f === g; // false
f.expando = 'foo';
g.expando; // undefined

これを見ると、どのオブジェクトを変更しても他のオブジェクトは変更されないため、誰もが問題は深刻であると考えるでしょう。この例では、2 つの異なるオブジェクトを作成することがわかります。つまり、f の属性を変更して特定の情報を保存し、それを当然のことながら、g の同じ name 属性を参照して使用する場合です。同じオブジェクトの場合、それはまったく不可能であるため、大きな問題が発生します。

もう少し複雑な例を見てみましょう:

例 4: 関数宣言のみを順番に解析し、条件付きステートメント ブロックを無視します

var f = function g() {
  return 1;
};
if (false) {
 f = function g(){
 return 2;
 };
}
g(); // 2

このバグは見つけるのが非常に困難ですが、バグの原因は非常に単純です。まず、g は関数宣言として解析されます。JScript の関数宣言は条件付きコード ブロックの対象ではないため、この厄介な if 分岐では、g は別の関数 function g(){ return 2 } として扱われ、再度宣言されただけです。 。次に、すべての「正規」表現が評価され、新しく作成された別のオブジェクトへの参照が f に与えられます。式が評価されるときに忌まわしい if 分岐 "" が入力されることはないため、 f は最初の関数 function g(){ return 1 } を参照し続けます。これを分析すると、問題は非常に明確になります。十分注意して f で g を呼び出すと、無関係な g 関数オブジェクトが

と呼ばれます。

arguments.callee を使用してさまざまなオブジェクトを比較した場合の違いは何なのかと疑問に思われるかもしれません。見てみましょう:

var f = function g(){
  return [
  arguments.callee == f,
  arguments.callee == g
  ];
};
f(); // [true, false]
g(); // [false, true]

ご覧のとおり、arguments.callee の参照は常に呼び出される関数です。これは、後で説明するように、実際には良いことです。

もう 1 つの興味深い例は、宣言を含まない代入ステートメントで名前付き関数式を使用することです。

(function(){
 f = function f(){};
})();

コード分析によると、最初はグローバル属性 f を作成する必要がありました (名前付き宣言を使用する一般的な匿名関数と混同しないように注意してください)。まず、式が変更されました。式は関数宣言として解析されるため、左側の f はローカル変数として宣言されます (一般的な無名関数の宣言と同じ)。関​​数が実行されるときには、f はすでに定義されており、関数 f( ) 右側の {} はローカル変数 f に直接割り当てられているため、f はグローバル属性ではありません。

JScript がいかに異常であるかを理解した後、まず、識別子が外部スコープに漏洩しないようにする必要があります。次に、関数名として使用される識別子を引用符で囲んではなりません。グラム? ——gが存在しないふりをすることができれば、どれだけ無用なトラブルを避けることができるでしょうか。したがって、重要なのは、常に f または argument.callee を介して関数を参照することです。名前付き関数式を使用する場合は、デバッグ時にのみその名前を使用する必要があります。最後に、名前付き関数式の宣言中に誤って作成された関数をクリーンアップすることを忘れないでください。

2. JScript のメモリ管理

これらの非標準コード解析のバグを理解した後、それを使用すると、実際にはメモリに問題があることがわかります。例を見てみましょう。

var f = (function(){
 if (true) {
 return function g(){};
 }
 return function g(){};
})();

我们知道,这个匿名函数调用返回的函数(带有标识符g的函数),然后赋值给了外部的f。我们也知道,命名函数表达式会导致产生多余的函数对象,而该对象与返回的函数对象不是一回事。所以这个多余的g函数就死在了返回函数的闭包中了,因此内存问题就出现了。这是因为if语句内部的函数与g是在同一个作用域中被声明的。这种情况下 ,除非我们显式断开对g函数的引用,否则它一直占着内存不放。

var f = (function(){
 var f, g;
 if (true) {
 f = function g(){};
 }
 else {
 f = function g(){};
 }
 // 设置g为null以后它就不会再占内存了
 g = null;
 return f;
})();

通过设置g为null,垃圾回收器就把g引用的那个隐式函数给回收掉了,为了验证我们的代码,我们来做一些测试,以确保我们的内存被回收了。

测试

测试很简单,就是命名函数表达式创建10000个函数,然后把它们保存在一个数组中。等一会儿以后再看这些函数到底占用了多少内存。然后,再断开这些引用并重复这一过程。下面是测试代码:

function createFn(){
 return (function(){
 var f;
 if (true) {
  f = function F(){
  return 'standard';
  };
 }
 else if (false) {
  f = function F(){
  return 'alternative';
  };
 }
 else {
  f = function F(){
  return 'fallback';
  };
 }
 // var F = null;
 return f;
 })();
}

var arr = [ ];
for (var i=0; i < 10000; i++) {
 arr[i] = createFn();
}

通过运行在Windows XP SP2中的任务管理器可以看到如下结果:

IE7:

 without `null`: 7.6K -> 20.3K
 with `null`:  7.6K -> 18K

IE8:

 without `null`: 14K -> 29.7K
 with `null`:  14K -> 27K

如我们所料,显示断开引用可以释放内存,但是释放的内存不是很多,10000个函数对象才释放大约3M的内存,这对一些小型脚本不算什么,但对于大型程序,或者长时间运行在低内存的设备里的时候,这是非常有必要的。

以上就是关于JScript的Bug与内存管理的全部介绍,希望对大家的学习有所帮助。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの進化:現在の傾向と将来の見通しJavaScriptの進化:現在の傾向と将来の見通しApr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

javascriptの分解:それが何をするのか、なぜそれが重要なのかjavascriptの分解:それが何をするのか、なぜそれが重要なのかApr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境