Nodejs 入門 Study Notes_node.js

WBOY
WBOYオリジナル
2016-05-16 16:03:361082ブラウズ

NodeJS に関する最初の記事を共有します。JavaScript の一般知識と、JavaScript 開発者から NodeJS 開発者に移行する方法 (特定のフレームワークは紹介されません)。この記事を読む前に、JavaScript について予備知識を持っておいていただければ幸いです。

JavaScript は、プロトタイプ モデルに基づいたインタープリタ型言語です。 NodeJS の解釈については後述します。プロトタイプ チェーンは ES6 より前の Javascript のオブジェクト指向実装メソッドの 1 つであり、ES6 でサポートされるクラスに新しい実装メソッドが追加されます。 Javascript では、「クラス」も含めてすべてがオブジェクトです。 Ruby/Python のメタプログラミングを経験したことのある人には、これが非常に馴染みがあると思われるかもしれません。JavaScript はクラスを動的に生成するメソッドを簡単に実装できます。

1. プロトタイプチェーンに基づいて実装された単純な「クラス」

var Person = function(name){
 this.name = name;
};

Person.staticSay = function(name){
 console.log('Hello ' + name);
};

Person.prototype.sayHi = function(){
 Person.staticSay(this.name);
}

Javascript のすべてのメソッドはキャメルケースで名前が付けられ、一重引用符が優先され、2 つのスペースが使用されるなど、いくつかの共通仕様について言及します。詳細な仕様については、https://github.com を参照してください。 /airbnb/ JavaScript

コード内の

staticSay は静的メソッドです。つまり、Person.staticSay を通じてのみ呼び出すことができます。 上記の Person がインスタンスを生成すると (例: var vincent = new Person('vincent'); )、vincent は Person.prototype のすべてのメソッドを自動的に継承します (コード内のこれは、上記の vincent である現在のコンテキストを指します)。 。

同時に、次のコードのようにメソッドをオブジェクト vincent に動的に追加することもできます。

var vincent = new Person('vincent')
vincent.tellName = function(){
 console.log('Hi, i\'m am' + this.name)
};

継承をシミュレートする必要がある場合は、プロトタイプに取り組む必要があります。たとえば、これを実現するために、以下では Worker.prototype = new Person() が使用され、 new Person() によって返されるインスタンス オブジェクトのすべてのメソッドとプロパティがプロトタイプに割り当てられ、偽装継承がシミュレートされます。このメソッドは、最終的にプロトタイプの内容をレイヤーごとに検索します (各インスタンスのメソッドはプロトタイプ内にあり、オブジェクトに至るため)。もちろん、トラバーサルを通じてプロトタイプに値を代入することで継承をシミュレートすることもできます。

2. コンテキストの切り替え

コンテキストの最も直観的な表現は、コード ブロック内でのこれです。これは通常、オブジェクト指向プログラミングで、現在の「クラス」によって生成された対応するインスタンスを参照するために使用され、他の言語の self と一貫性があります。

引き続き上記の例を使用すると、上で Person.prototype.sayHi メソッドが実装されました。コードは次のとおりです。

var Cat = function(name){
 this.name = name;
}

var c = new Cat('tomcat');

ある日突然、猫に人間のように自己紹介してもらいたいと思ったらどうしますか?猫はsayHiメソッドを持っていません。しかし、人間のsayHiメソッドはconsole.log(person.prototype.sayHi)を通じて取得できますが、どうすれば猫もそれを使用できるのでしょうか?

JavaScript には call と apply という 2 つのメソッドがあり、それらの違いはパラメータが異なること (自分で調べてください) と、その機能がコンテキストを切り替えることです。簡単に言うと、 Person.prototype.sayHi 関数内のこれを他のオブジェクトに変更できます。使用法: person.prototype.sayHi.call(c)。

これは実用的ですか?たとえば、次のシナリオ:

var doSomething = function(){
 var persons = arguments;
};
上記の関数では、無限の数のパラメーターをサポートするために、すべてのパラメーターがキーワード引数を通じて取得されます。ここで、もともと Array 型に属していたいくつかのメソッドを人物に対して使用したいと思います。これを実現するにはどうすればよいでしょうか。ここでコンテキスト切り替えを使用できます:

var doSomething = function(){
 var persons = arguments;
 // 使用 Array 的 slice 方法,将 arguments 对象转变为 Array 实例
 var persons_arr = Array.prototype.slice.call(arguments);
};

3. 終了

共通のコードから始めましょう

for (var i = 0; i < 3; i ++){
 setTimeout(function(){
  console.log(i);
 }, i)
}
これの出力は何でしょうか? 0 1 2 を順番に出力しますか?実際の状況では、setTimeout が初めてコールバックを実行するとき、for ループは終了しています。これは、この時点で i がすでに 3 であることを意味し、最終的な出力結果は 3 3 3 になります。

周囲のコードの影響を受けないように変数を保護する必要がある場合は、クロージャ (スコープが閉じられたコードのブロック) を検討する必要があるかもしれません。

for (var i = 0; i < 3; i ++){
 +function(i){
  setTimeout(function(){
   console.log(i);
  }, i)
 }(i)
}
ねえ、これは何のためにあるの? 他に方法がある場合は、自分で Google で調べてください。クロージャ内の i のスコープはクローズドスコープなので、最終的にクロージャ内の i は外部実行によって変更されていないため、正常に 0 1 2 が出力されます。

JavaScript のいくつかの機能、キーワード プロトタイプ チェーン、呼び出しと適用、および引数キーワードの簡単な紹介。さらに詳しい情報については、権威あるガイドなどの書籍を読むか、基本的な型と各型の特性を簡単に理解できます。方法。現在のコードの文字列を取得し、それを処理して必要なコンテンツを取得したり、ユーザーがオブジェクトのプロパティに値を取得または割り当てたりするときにゲッターとセッターを使用して特別な操作を実行するなど、さらにいくつかの魔法のコードがあります。等

4. NodeJS と Javascript 開発の違い

このセクションでは主に、requireloading の基本的な知識を紹介します。まず、いくつかのコードを紹介します。

// a.js
module.exports = {
 name: "a",
 doSomething: function(){
  return "something";
 }
}

// b.js
var a = require('./a')
global.a_name = a.name;

// c.js
require('./b');
console.log(a_name) // 执行后打印 a 

ノード c.js を実行すると何が起こるでしょうか?

require はノードのキーワードです。NodeJS は非同期であることで有名ですが、その require はブロックします。そうしないと、他のモジュールがロードされる前に次のコードがすでに実行を開始している状況が発生します。

require.resolve() メソッドは、参照するファイルの実際のパスを見つけるために使用されます。見つけた後、Nodejs は require.cache を調べてキャッシュがあるかどうかを確認します。キャッシュがない場合は、ファイルを作成して解析するため、通常、この場合、js ファイル内の実行コードは、最初に必要になったときにのみ実行されます。 (tip. require.cache は必要に応じて手動で削除すれば、ある程度は複数回実行可能です)

b.js の実行が開始されると、最初に a.js をロードする必要があります。module.exports は、このファイルが外部に公開される内容を Nodejs に伝えます。たとえば、a.js は name 属性やdoSomething メソッド。 b.js の変数は実際にはこのオブジェクトです。

a.js を取得するために実行した後、続けて b.js に戻ります。 global.a_name は、フロントエンドの window.a_name = a.name と同様の効果があります。

最終処理が完了し、出力された値をc.jsが実行します。

5. 非同期の基本原理

NodeJS は、人々に使用されているような錯覚を与えやすいものです。つまり、長い間書いた後でも、基礎となる非同期がどのように実装されているかわからない場合があります。 (以下の理解は主に python3.4 の asyncio の理解を基にしています。間違いがあればご指摘ください。)

NodeJS の基礎となる libev は、Window では IOCP を使用し、*nix では AIO ベースの libeio を使用して、非同期実装を実現します。システム レベルのテクノロジを通じて、最終的に 1 つの目標が達成されます。つまり、アプリケーションが非同期リクエストを開始し、システムが実行を完了した後、システムはアプリケーションに処理が完了したことを通知します。このプロセス中、アプリケーションは前の処理を一時停止またはスレッド プールにプッシュして実行を待機することができ、この期間中にアプリケーションは他のタスクを実行できます。

操作全体はシステムレベルのイベントループを通じて実行されます。たとえば、Python には、非同期実行前にプログラムが終了しないようにするための run_until および run_forever に似たメソッドが用意されています。非同期操作全体を、常に実行されているワークショップとして考えてください。ワークショップ内の機械は、パッケージを確認してスタンプを押し、パッケージを受け取り、対応するラベルを付けてワークショップに戻します。作業者は、以前にパッケージに貼り付けたラベルと作業場によって貼られたラベルに基づいて、次の処理ステップを実行します。作業者は、次の荷物に移る前に荷物の検査を待つ必要はなく、簡単な処理を受け入れてから検査のために作業場に入れるだけで済みます。次に、ワークショップが特定の時間に荷物を返してくるのを待って、次のステップに進みます。

現時点では、主に言語レベルの知識のみを紹介していますが、これだけでは、後で紹介する完全な Web の開発にはまだ少し距離があります。 Redis、Nginx、テストドライバーなどが含まれます。

以上がこの記事の全内容です。皆さんに気に入っていただければ幸いです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。