ここでは、JavaScript の非同期プログラミング テクノロジについて詳しく説明します。 (追伸。この記事は長いので、メロンの種とコーラをご用意ください:D)
1. Javascript 非同期プログラミングの紹介
少なくとも言語レベルでは、JavaScript はシングルスレッドであるため、非同期プログラミングは特に重要です。それ。
nodejs を例にとると、シェルはユーザー操作のレベルである js 言語の層であり、このレベルでは単一のスレッドで実行されます。つまり、次のような言語レベルでマルチスレッドを使用することはできません。 JavaやPythonなどの言語能力。代わりに、nodejs プログラミングでは、同期ブロックを発生させずにハードウェアを効率的に使用するために、非同期プログラミング テクノロジを広範囲に使用します。ただし、nodejs の基盤となる実装では実際にはマルチスレッド テクノロジが使用されていますが、この層はユーザーに透過的に行われ、マルチスレッド プログラミングで発生するロックやその他の問題について心配する必要はありません。問題は、非同期コードを書くだけです。
2。 ES 7:
* async と await PS: 以下の例を実行したい場合は、node v0.11 以降をインストールし、node [ファイル名.js] を使用してコマンドラインで実行してください。一部のコード 特別なオプションを有効にする必要があります。これについては、具体的な例で説明します。
1. コールバック関数
//一个定时器function timer(time, callback){ setTimeout(function(){ callback(); }, time); } timer(3000, function(){ console.log(123); })例 2:
//读文件后输出文件内容var fs = require('fs'); fs.readFile('./text1.txt', 'utf8', function(err, data){ if (err){ throw err; } console.log(data); });例 3:
1 //嵌套回调,读一个文件后输出,再读另一个文件,注意文件是有序被输出的,先text1.txt后text2.txt2 var fs = require('fs');3 4 fs.readFile('./text1.txt', 'utf8', function(err, data){5 console.log("text1 file content: " + data);6 fs.readFile('./text2.txt', 'utf8', function(err, data){7 console.log("text2 file content: " + data);8 });9 });例 4:
1 //callback hell 2 3 doSomethingAsync1(function(){ 4 doSomethingAsync2(function(){ 5 doSomethingAsync3(function(){ 6 doSomethingAsync4(function(){ 7 doSomethingAsync5(function(){ 8 // code... 9 });10 });11 });12 });13 });上記の 4 つの例を観察すると、コールバック関数のネスト レベルの数が深くない場合に問題が発生することがわかります。 . 、コードは比較的理解しやすく、保守しやすいです。ネスト層の数が深くなると、例 4 のように「コールバック ピラミッド」の問題が発生します。各コールバック関数に多くのビジネス ロジックが含まれる場合、コード ブロック全体が複雑になります。非常に複雑になります。上記のコールバック関数の書き方は、論理的には問題ありませんが、ビジネスロジックが増大し、複雑化すると、この書き方の欠点がすぐに露呈してしまい、メンテナンスが非常に困難になります。 . それは「コールバック地獄」と呼ばれるほど辛いです。 コールバック階層の複雑さを測定する方法は、doSomethingAsync1 の前に doSomethingAsync2 が発生すると仮定して、例 4 でどれだけのリファクタリングの苦痛に耐えなければならないかです。 コールバック関数のもう 1 つの問題は、コールバック関数の外でコールバック関数内で例外をキャッチできないことです。例外を処理するときにこれを行っていました。例 5:
1 try{2 //do something may cause exception..3 }4 catch(e){5 //handle exception...6 }
1 var fs = require('fs'); 2 3 try{ 4 fs.readFile('not_exist_file', 'utf8', function(err, data){ 5 console.log(data); 6 }); 7 } 8 catch(e){ 9 console.log("error caught: " + e);10 }
出力はどうなると思いますか?答えは未定義です。存在しないファイルを読み取ろうとすると、当然例外がスローされますが、最も外側の try/catch ステートメントはこの例外をキャッチできません。これは、非同期コードの実行メカニズムが原因で発生します。
ヒント: 非同期コードのコールバック関数の例外が最も外側の try/catch ステートメントでキャッチできないのはなぜですか? 非同期呼び出しは通常、リクエストの送信と結果の処理という 2 つの段階に分かれています。 2 つのステージのループ呼び出し。これらは 2 つの異なるイベント ループ (ティック) に属しており、互いに関連しません。 try/catch ステートメントは、現在のイベント ループの例外をキャプチャすることのみができ、コールバックでは何も実行できません。 つまり、非同期呼び出し関数で非同期 I/O リクエストをスローすると、非同期呼び出し関数はすぐに戻ります。このとき、非同期呼び出し関数は非同期 I/O リクエストとは何の関係もありません。 イベント リスニングは、非常に一般的な非同期プログラミング パターンであり、コードの分離に非常に役立ちます。通常、どの部分が定数で、どの部分が変更しやすいかを考慮する必要があります。外部呼び出し用に定数部分をコンポーネント内にカプセル化し、カスタマイズが必要な部分を外部処理用に公開します。ある意味、イベントの設計はコンポーネントのインターフェイス設計です。 例 7:1 //发布和订阅事件 2 3 var events = require('events'); 4 var emitter = new events.EventEmitter(); 5 6 emitter.on('event1', function(message){ 7 console.log(message); 8 }); 9 10 emitter.emit('event1', "message for you");
イベント リスニング処理を使用するこの非同期プログラミング手法は、高度な分離が必要な一部のシナリオに非常に適しています。たとえば、以前のゲーム サーバー プロジェクトでは、キャラクターの属性が変更されると、永続化レイヤーに書き込む必要がありました。解決策は、最初にサブスクライバーを作成し、「save」イベントをサブスクライブし、データを保存する必要があるときに、パブリッシャー オブジェクト (ここではキャラクター オブジェクト) が直接 Emit を使用してイベント名を送信し、対応するパラメーターを渡すことです。 、サブスクライバはこのイベント情報を受信して処理されます。
3.Promise对象
ES 6中原生提供了Promise对象,Promise对象代表了某个未来才会知道结果的事件(一般是一个异步操作),并且这个事件对外提供了统一的API,可供进一步处理。
使用Promise对象可以用同步操作的流程写法来表达异步操作,避免了层层嵌套的异步回调,代码也更加清晰易懂,方便维护。
Promise.prototype.then()
Promise.prototype.then()方法返回的是一个新的Promise对象,因此可以采用链式写法,即一个then后面再调用另一个then。如果前一个回调函数返回的是一个Promise对象,此时后一个回调函数会等待第一个Promise对象有了结果,才会进一步调用。
example 8:
1 //ES 6原生Promise示例 2 var fs = require('fs') 3 4 var read = function (filename){ 5 var promise = new Promise(function(resolve, reject){ 6 fs.readFile(filename, 'utf8', function(err, data){ 7 if (err){ 8 reject(err); 9 }10 resolve(data);11 })12 });13 return promise;14 }15 16 read('./text1.txt')17 .then(function(data){18 console.log(data);19 }, function(err){20 console.log("err: " + err);21 });
上面这个例子,Promise构造函数的参数是一个函数,在这个函数中我们写异步操作的代码,在异步操作的回调中,我们根据err变量来选择是执行resolve方法还是reject方法,一般来说调用resolve方法的参数是异步操作获取到的数据(如果有的话),但还可能是另一个Promise对象,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作,调用reject方法的参数是异步回调用的err参数。
调用read函数时,实际上返回的是一个Promise对象,通过在这个Promise对象上调用then方法并传入resolve方法和reject方法来指定异步操作成功和失败后的操作。
example 9:
1 //原生Primose顺序嵌套回调示例 2 var fs = require('fs') 3 4 var read = function (filename){ 5 var promise = new Promise(function(resolve, reject){ 6 fs.readFile(filename, 'utf8', function(err, data){ 7 if (err){ 8 reject(err); 9 }10 resolve(data);11 })12 });13 return promise;14 }15 16 read('./text1.txt')17 .then(function(data){18 console.log(data);19 return read('./text2.txt');20 })21 .then(function(data){22 console.log(data);23 });
异常处理
Promise.prototype.catch()
Promise.prototype.catch方法是Promise.prototype.then(null, rejection)的别名,用于指定发生错误时的回调函数。
example 9:
1 var fs = require('fs') 2 3 var read = function (filename){ 4 var promise = new Promise(function(resolve, reject){ 5 fs.readFile(filename, 'utf8', function(err, data){ 6 if (err){ 7 reject(err); 8 } 9 resolve(data);10 })11 });12 return promise;13 }14 15 read('./text1.txt')16 .then(function(data){17 console.log(data);18 return read('not_exist_file');19 })20 .then(function(data){21 console.log(data);22 })23 .catch(function(err){24 console.log("error caught: " + err);25 })26 .then(function(data){27 console.log("completed");28 })
如果在catch方法中发生了异常:
example 10:
1 var fs = require('fs') 2 3 var read = function (filename){ 4 var promise = new Promise(function(resolve, reject){ 5 fs.readFile(filename, 'utf8', function(err, data){ 6 if (err){ 7 reject(err); 8 } 9 resolve(data);10 })11 });12 return promise;13 }14 15 read('./text1.txt')16 .then(function(data){17 console.log(data);18 return read('not_exist_file');19 })20 .then(function(data){21 console.log(data);22 })23 .catch(function(err){24 console.log("error caught: " + err);25 x+1;26 })27 .then(function(data){28 console.log("completed");29 })
我们可以在catch方法后再加catch方法来捕获这个x+1的异常:
example 11:
1 var fs = require('fs') 2 3 var read = function (filename){ 4 var promise = new Promise(function(resolve, reject){ 5 fs.readFile(filename, 'utf8', function(err, data){ 6 if (err){ 7 reject(err); 8 } 9 resolve(data);10 })11 });12 return promise;13 }14 15 read('./text1.txt')16 .then(function(data){17 console.log(data);18 return read('not_exist_file');19 })20 .then(function(data){21 console.log(data);22 })23 .catch(function(err){24 console.log("error caught: " + err);25 x+1;26 })27 .catch(function(err){28 console.log("error caught: " + err);29 })30 .then(function(data){31 console.log("completed");32 })
如果几个异步调用有关联,但它们不是顺序式的,是可以同时进行的,我们很直观地会希望它们能够并发执行(这里要注意区分“并发”和“并行”的概念,不要搞混)。
Promise.all()
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3]);
Promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象实例。
p的状态由p1、p2、p3决定,分两种情况:
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
一个具体的例子:
example 12:
1 var fs = require('fs') 2 3 var read = function (filename){ 4 var promise = new Promise(function(resolve, reject){ 5 fs.readFile(filename, 'utf8', function(err, data){ 6 if (err){ 7 reject(err); 8 } 9 resolve(data);10 })11 });12 return promise;13 }14 15 var promises = [1, 2].map(function(fileno){16 return read('./text' + fileno + '.txt');17 });18 19 Promise.all(promises)20 .then(function(contents){21 console.log(contents);22 })23 .catch(function(err){24 console.log("error caught: " + err);25 })
Promise.race()
Promise.race()也是将多个Promise实例包装成一个新的Promise实例:
var p = Promise.race([p1,p2,p3]);
上述代码中,p1、p2、p3只要有一个实例率先改变状态,p的状态就会跟着改变,那个率先改变的Promise实例的返回值,就传递给p的返回值。如果Promise.all方法和Promise.race方法的参数不是Promise实例,就会先调用下面讲到的Promise.resolve方法,将参数转为Promise实例,再进一步处理。
example 13:
1 var http = require('http'); 2 var qs = require('querystring'); 3 4 var requester = function(options, postData){ 5 var promise = new Promise(function(resolve, reject){ 6 var content = ""; 7 var req = http.request(options, function (res) { 8 res.setEncoding('utf8'); 9 10 res.on('data', function (data) {11 onData(data);12 });13 14 res.on('end', function () {15 resolve(content);16 });17 18 function onData(data){19 content += data;20 }21 });22 23 req.on('error', function(err) {24 reject(err);25 });26 27 req.write(postData);28 req.end();29 });30 31 return promise;32 }33 34 var promises = ["柠檬", "苹果"].map(function(keyword){35 var options = {36 hostname: 'localhost', 37 port: 9200, 38 path: '/meiqu/tips/_search',39 method: 'POST' 40 };41 42 var data = {43 'query' : {44 'match' : {45 'summary' : keyword46 }47 }48 };49 data = JSON.stringify(data);50 return requester(options, data);51 });52 53 Promise.race(promises)54 .then(function(contents) {55 var obj = JSON.parse(contents);56 console.log(obj.hits.hits[0]._source.summary);57 })58 .catch(function(err){59 console.log(err); 60 });
有时候需将现有对象转换成Promise对象,可以使用Promise.resolve()。
如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为fulfilled。
如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回。
example 14:
1 var p = Promise.resolve('Hello');2 3 p.then(function (s){4 console.log(s)5 });
Promise.reject()
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
example 15:
1 var p = Promise.reject('出错了');2 3 p.then(null, function (s){4 console.log(s)5 });
上面代码生成一个Promise对象的实例p,状态为rejected,回调函数会立即执行。
3.Generator函数
Generator函数是协程在ES 6中的实现,最大特点就是可以交出函数的执行权(暂停执行)。
注意:在node中需要开启–harmony选项来启用Generator函数。
整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。
协程的运行方式如下:
第一步:协程A开始运行。
第二步:协程A执行到一半,暂停,执行权转移到协程B。
第三步:一段时间后,协程B交还执行权。
第四步:协程A恢复执行。
上面的协程A就是异步任务,因为分为两步执行。
比如一个读取文件的例子:
example 16:
1 function asnycJob() {2 // ...其他代码3 var f = yield readFile(fileA);4 // ...其他代码5 }
asnycJob函数是一个协程,yield语句表示,执行到此处执行权就交给其他协程,也就是说,yield是两个阶段的分界线。协程遇到yield语句就暂停执行,直到执行权返回,再从暂停处继续执行。这种写法的优点是,可以把异步代码写得像同步一样。
看一个简单的Generator函数例子:
example 17:
1 function* gen(x){ 2 var y = yield x + 2; 3 return y; 4 } 5 6 var g = gen(1); 7 var r1 = g.next(); // { value: 3, done: false } 8 console.log(r1); 9 var r2 = g.next() // { value: undefined, done: true }10 console.log(r2);
上述代码中,调用Generator函数,会返回一个内部指针(即遍历器)g,这是Generator函数和一般函数不同的地方,调用它不会返回结果,而是一个指针对象。调用指针g的next方法,会移动内部指针,指向第一个遇到的yield语句,上例就是执行到x+2为止。
换言之,next方法的作用是分阶段执行Generator函数。每次调用next方法,会返回一个对象,表示当前阶段的信息(value属性和done属性)。value属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示Generator函数是否执行完毕,即是否还有下一个阶段。
Generator函数的数据交换和错误处理
next方法返回值的value属性,是Generator函数向外输出数据;next方法还可以接受参数,这是向Generator函数体内输入数据。
example 18:
1 function* gen(x){ 2 var y = yield x + 2; 3 return y; 4 } 5 6 var g = gen(1); 7 var r1 = g.next(); // { value: 3, done: false } 8 console.log(r1); 9 var r2 = g.next(2) // { value: 2, done: true }10 console.log(r2);
Generator函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。
example 19:
1 function* gen(x){ 2 try { 3 var y = yield x + 2; 4 } 5 catch (e){ 6 console.log(e); 7 } 8 return y; 9 }10 11 var g = gen(1);12 g.next();13 g.throw('error!'); //error!
example 20:
1 var fs = require('fs'); 2 var thunkify = require('thunkify'); 3 var readFile = thunkify(fs.readFile); 4 5 var gen = function* (){ 6 var r1 = yield readFile('./text1.txt', 'utf8'); 7 console.log(r1); 8 var r2 = yield readFile('./text2.txt', 'utf8'); 9 console.log(r2);10 };11 12 //开始执行上面的代码13 var g = gen();14 15 var r1 = g.next();16 r1.value(function(err, data){17 if (err) throw err;18 var r2 = g.next(data);19 r2.value(function(err, data){20 if (err) throw err;21 g.next(data);22 });23 });
在深入讨论Generator函数之前我们先要知道Thunk函数这个概念。
求值策略(即函数的参数到底应该何时求值)
(1) 传值调用
(2) 传名调用
Javascript是传值调用的,Thunk函数是编译器“传名调用”的实现,就是将参数放入一个临时函数中,再将这个临时函数放入函数体,这个临时函数就叫做Thunk函数。
举个栗子就好懂了:
example 21:
1 function f(m){ 2 return m * 2; 3 } 4 var x = 1; 5 f(x + 5); 6 7 //等同于 8 var thunk = function (x) { 9 return x + 5;10 };11 12 function f(thunk){13 return thunk() * 2;14 }
JavaScript语言的Thunk函数
在JavaScript语言中,Thunk函数替换的不是表达式,而是多参数函数,将其替换成单参数的版本,且只接受回调函数作为参数。
example 22:
1 var fs = require('fs'); 2 3 // 正常版本的readFile(多参数版本) 4 fs.readFile(fileName, callback); 5 6 // Thunk版本的readFile(单参数版本) 7 var readFileThunk = Thunk(fileName); 8 readFileThunk(callback); 9 10 var Thunk = function (fileName){11 return function (callback){12 return fs.readFile(fileName, callback);13 };14 };
example 23:
1 var Thunk = function(fn){2 return function (){3 var args = Array.prototype.slice.call(arguments);4 return function (callback){5 args.push(callback);6 return fn.apply(this, args);7 }8 };9 };
使用上面的转换器,生成fs.readFile的Thunk函数。
example 24:
1 var readFileThunk = Thunk(fs.readFile);2 readFileThunk('./text1.txt', 'utf8')(function(err, data){3 console.log(data);4 });
可以使用thunkify模块来Thunk化任何带有callback的函数。
我们需要借助Thunk函数的能力来自动执行Generator函数。
下面是一个基于Thunk函数的Generator函数执行器。
example 25:
1 //Generator函数执行器 2 3 function run(fn) { 4 var gen = fn(); 5 6 function next(err, data) { 7 var result = gen.next(data); 8 if (result.done) return; 9 result.value(next);10 }11 12 next();13 }14 15 run(gen);
example 26:
1 var fs = require('fs'); 2 var thunkify = require('thunkify'); 3 var readFile = thunkify(fs.readFile); 4 5 var gen = function* (){ 6 var f1 = yield readFile('./text1.txt', 'utf8'); 7 console.log(f1); 8 var f2 = yield readFile('./text2.txt', 'utf8'); 9 console.log(f2);10 var f3 = yield readFile('./text3.txt', 'utf8');11 console.log(f3);12 };13 14 function run(fn) {15 var gen = fn();16 17 function next(err, data) {18 var result = gen.next(data);19 if (result.done) return;20 result.value(next);21 }22 23 next();24 }25 26 run(gen); //自动执行
yield *语句
普通的yield语句后面跟一个异步操作,yield *语句后面需要跟一个遍历器,可以理解为yield *后面要跟另一个Generator函数,讲起来比较抽象,看一个实例。
example 27:
1 //嵌套异步操作流 2 var fs = require('fs'); 3 var thunkify = require('thunkify'); 4 var readFile = thunkify(fs.readFile); 5 6 var gen = function* (){ 7 var f1 = yield readFile('./text1.txt', 'utf8'); 8 console.log(f1); 9 10 var f_ = yield * gen1(); //此处插入了另外一个异步流程11 12 var f2 = yield readFile('./text2.txt', 'utf8');13 console.log(f2);14 15 var f3 = yield readFile('./text3.txt', 'utf8');16 console.log(f3);17 };18 19 var gen1 = function* (){20 var f4 = yield readFile('./text4.txt', 'utf8');21 console.log(f4);22 var f5 = yield readFile('./text5.txt', 'utf8');23 console.log(f5);24 }25 26 function run(fn) {27 var gen = fn();28 29 function next(err, data) {30 var result = gen.next(data);31 if (result.done) return;32 result.value(next);33 }34 35 next();36 }37 38 run(gen); //自动执行
1
4
5
2
3
也就是说,使用yield *可以在一个异步操作流程中直接插入另一个异步操作流程,我们可以据此构造可嵌套的异步操作流,更为重要的是,写这些代码完全是同步风格的。
目前业界比较流行的Generator函数自动执行的解决方案是co库,此处也只给出co的例子。顺带一提node-fibers也是一种解决方案。
顺序执行3个异步读取文件的操作,并依次输出文件内容:
example 28:
1 var fs = require('fs'); 2 var co = require('co'); 3 var thunkify = require('thunkify'); 4 var readFile = thunkify(fs.readFile); 5 6 co(function*(){ 7 var files=[ 8 './text1.txt', 9 './text2.txt',10 './text3.txt'11 ];12 13 var p1 = yield readFile(files[0]);14 console.log(files[0] + ' ->' + p1);15 16 var p2 = yield readFile(files[1]);17 console.log(files[1] + ' ->' + p2);18 19 var p3 = yield readFile(files[2]);20 console.log(files[2] + ' ->' + p3);21 22 return 'done';23 });
example 29:
1 var fs = require('fs'); 2 var co = require('co'); 3 var thunkify = require('thunkify'); 4 var readFile = thunkify(fs.readFile); 5 6 co(function* () { 7 var files = ['./text1.txt', './text2.txt', './text3.txt']; 8 var contents = yield files.map(readFileAsync); 9 10 console.log(contents);11 });12 13 function readFileAsync(filename) {14 return readFile(filename, 'utf8');15 }
ES 7中的async和await
async和await是ES 7中的新语法,新到连ES 6都不支持,但是可以通过Babel一类的预编译器处理成ES 5的代码。目前比较一致的看法是async和await是js对异步的终极解决方案。
async函数实际上是Generator函数的语法糖(js最喜欢搞语法糖,包括ES 6中新增的“类”支持其实也是语法糖)。
配置Babel可以看:配置Babel
如果想尝个鲜,简单一点做法是执行:
1 sudo npm install --global babel-cli
async_await.js代码如下:
1 var fs = require('fs'); 2 3 var readFile = function (fileName){ 4 return new Promise(function (resolve, reject){ 5 fs.readFile(fileName, function(error, data){ 6 if (error){ 7 reject(error); 8 } 9 else {10 resolve(data);11 }12 });13 });14 };15 16 var asyncReadFile = async function (){17 var f1 = await readFile('./text1.txt');18 var f2 = await readFile('./text2.txt');19 console.log(f1.toString());20 console.log(f2.toString());21 };22 23 asyncReadFile();
输出:
1
2
相关文章:
深入理解JavaScript编程中的同步与异步机制_基础知识
以上がJavascript非同期プログラミングの知識を体系的に解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

Dreamweaver Mac版
ビジュアル Web 開発ツール

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ホットトピック









