ホームページ >ウェブフロントエンド >jsチュートリアル >分かりやすいJavaScriptチュートリアル(完全集)_JavaScriptスキル

分かりやすいJavaScriptチュートリアル(完全集)_JavaScriptスキル

PHP中文网
PHP中文网オリジナル
2016-05-16 19:00:091144ブラウズ

私の本「JavaScript 言語の本質とプログラミング実践」は読みにくいと思っている読者が多いので、私はずっと読みやすい本を書きたいと思っていました。とりあえず、今回は一番簡単なものを書いてみましょう。

「Programmer」の 2008 年 9 月号に「No Nonsense ErLang」という記事があり、「No Nonsense C」や「No Nansense Book Review」などの多くの記事を思い出しましたし、また次のような記事があると思いました。 JavaScript に関する「ナンセンスでない」記事がなかったので、この記事を書くことにしました。この決定に関連して、もう 1 つの理由があります。多くの読者が私の本『JavaScript 言語の本質とプログラミング実践』を読みにくいと考えているため、私は常に簡単な読み物本を書きたいと思っていました。とりあえず、今回は一番簡単なものを書いてみましょう。

免責事項: 複雑なことだけを読みたい場合は、この記事を読まないでください。
1. JavaScript はもともと手続き型でした
JavaScript は 1.0 時代に遡り、実際には手続き型です。基本的な機能は 2 つだけです。1 つは、Web ページの HTML
タグに直接配置してイベントを引き継ぐことができることです。たとえば、

コピー コード コードは次のとおりです。




2 番目item は、単純な Object コンストラクター (関数) をサポートします。実際、この時代のコンストラクターは初期化関数としては次のように記述する必要があります:

コードをコピー コードは次のとおりです:

function MyObject() {
this.xxx = '...';
this.yyy = '...';
}
obj = new MyObject();


したがって、初期の JavaScript には間違いなく「オブジェクトベースの手続き型スクリプト言語」というタイトルが付けられましたが、これはまったく不公平ではありません。
上記の 2 つの機能に加えて、JavaScript には次のような一般的なスクリプト言語プロパティがあります。
- .js ファイル全体が実行環境 (WEB ブラウザなど) に一度にロードされ、構文解析、行ごとの実行を開始します。
- 上記の構文解析サイクルでは、「var」で宣言された (名前付き) 関数と変数が、スクリプト コードで使用するために識別子テーブル内で前処理されます。 - グローバルなコード行または関数呼び出しから実行が開始され、プロセス全体で実行できないコードはエラー チェックされません (最初のステップでの構文エラー チェックを除く)。
には、一般的な手続き型言語のプロパティもあります。例:
- if/for/while/switch およびその他のステートメントがあります。
- 関数を宣言するには function を使用し、「(..)」を使用します。宣言するには、関数呼び出しとパラメータ転送を表す正式なパラメータ リスト、
- コード ブロックを表す「{..}」の使用、および「!=」などの演算記号、
- Java 言語に似たオブジェクト演算子「.」、およびプロパティやメソッドなどの基本的な概念。
これで、基本的な JavaScript 言語がわかりました。そのコードには C のような関数とステートメント行だけが含まれており、非常に単純な
オブジェクト指向プログラミングがサポートされています。 OK、これは実際には JavaScript のほぼすべてです...そうですね...文法の基本概念すべてです。少しでも入門的なプログラミング言語を使ったことがある人なら、JavaScript は実際には非常に単純であると感じるでしょう。
ええ、「関数を書いて呼び出す」、とても簡単です。例:
function hi() {
alert('hello, world.');
}
hi(); 2. データはもう少し複雑です。 type

JavaScript には 6 つの基本データ型があり、2 つのカテゴリに分類されます。 1 つの型は値の型、つまり未定義、文字列、数値、およびブール値であり、もう 1 つの型
は参照型、つまり関数とオブジェクトです。データ X のタイプを検出するには、「typeof X」を使用して文字列を返すだけです。 他の高級言語では、値型と参照型は「アクセス時に渡されるのが値か参照か」によって区別されます。簡単に言うと、次の関数 では、
function foo(X) {
}
X は、値自体、または値への参照として渡されます (ポインタ)、X 型が何であるかを示します。
他の言語とは異なり、JavaScript は値を渡す方法を記述するためのインジケーターを呼び出しエントリに追加しません。例:
function foo(var X) {
// 一般的な高級言語では、 var は合計値を示します。変数への参照です。例:
function foo(X) {
...
}
foo('123') // <- 文字列 '123' 値
foo(aObj); // <- aObj はオブジェクト参照です
この方法で処理できる鍵となるのは、JavaScript の型システムが十分に単純であるということです。 6 つの基本タイプには、実行可能と非実行可能、オブジェクトまたは非オブジェクト、存在 (価値) または不在 (価値) という 3 つの哲学的概念が含まれます。
のより複雑で自己完結型のロジックは、関数もオブジェクトであり、値もオブジェクトであり、無価値も値であるため、この哲学的考え方を理解するのは明らかに簡単ではありません。
JavaScript の型システムについては以上です。単純に使用したい場合は、次のことを覚えておくだけで十分です。
- 表示用に Web ページに渡すために、3 つの単純な値の型 (文字列、数値、ブール値) が使用されます。
- オブジェクトが使用されます。他のオブジェクト、関数、または上記の単純な値の型を保存し、「.」操作を使用して属性名を通じてそれらを検索します。
- データが有効か無効かを検出するために使用されます。を実行するために使用されます。
もちろん、もしあなたが言語学の思想家や狂人になりたいなら、先へ進んで上記の哲学的命題について考えてください。私はあなたを止めません。

3. 鼻でわかるのは直接測定

JavaScript での直接の量宣言は理解できない人も多いかもしれませんが、実際は非常に簡単です。現在、ほとんどの高級言語
が定数宣言をサポートしているため、最も原始的なアセンブリ言語でも即値をサポートしています。例:
// in C
#define ABYTE 256
// in delphi
const ABYTE = 256 ; in asm
mov ああ、256

それからもちろん JavaScript は... 直接測定をサポートできなければなりません恥じることなく、それらは実際には概念です。例:
// in javascript
var
aByte = 256
しかし、それを理解するときは、覚えておく必要があります。上記のすべてのコードにおいて、いわゆる直接量または即値は、それを指します。
変数または定数の識別子 ABYTE/aByte ではなく、' 256'。さらに、JavaScript は 8 種類の直接数量宣言をサポートしていることを知っておく必要があります。
---------------------
数値: 整数、浮動小数点数をサポートポイントと 0x はベース接頭辞に等しい、など;
ブール値: true/false;
値なし: 未定義;
関数: function() { ... }、匿名とも呼ばれます。関数
文字列: '..' または ".." を使用し、複数行とエスケープ文字をサポートします。
正規表現: /../.. を使用し、g、i、m などの通常の構成をサポートします。 > 配列: ネストされた配列をサポートするには [..] を使用します。
オブジェクト: ネストされたオブジェクト宣言をサポートするには {...} を使用します。 ---
上記の文字量は、コード内のどこでも個別に使用できます。つまり、式またはステートメント行です。鼻
を使用して行うことができる推論は次のとおりです。
//次のように書けるので、
aaa = 'hello, ' 'world';
// と書くことができるはずです。 :
bbb = [1,2,3] [4,5,6];
//同じように書くことができます:
ccc = /abc/ /cdf/
//同様に:
// ...
上記のように、すべての直接量を式またはステートメントの途中に置くことができます。場合によっては、構文解析の必要性により、直接量を囲むために一対の
括弧を使用する必要がある場合があります。そうしないと、次のような文法的曖昧さが生じます。
ddd = (function() { }) (function() {})
はい、直接測定するのはとても簡単です。あとは鼻がまだ劣化していないことを祈るだけです。
4. プロトタイプの継承
プロトタイプの継承は世界で最も単純なものかもしれません。
私たちはオブジェクトがテーブルであると仮定します - 偉大なアンダースは私の仮定を支持しています 彼は JavaScript オブジェクトが "プロパティ バッグ" であると言いました -
そのようなテーブルは "名前=値" のような "名前/値" ペアを格納します。 。次のコードを使用する場合:
aObj.name
値を見つけるために、テーブル内でそれを確認するだけです (Delphi を使用する人は TStringList を覚えておくとよいでしょう)。オブジェクト、ああ、いわゆるオブジェクト -
の以前の理解では - 「継承関係を持つ構造体 (構造体/レコード)」です。では、相続関係とは何でしょうか?
以上です。上記の検索が失敗した場合、プロトタイプ継承の場合は、aObj オブジェクトの「プロトタイプ」を検索するだけで済みます。
このプロトタイプもオブジェクトであり、コンストラクター関数のプロトタイプ属性に記録されます。例:
function MyObject() {
// ...
}
MyObject.prototype = xxx;
var aObj = new MyObject()
zzz = aObj.name ;
aObj で属性名が見つからない場合、上記のルールに従って、オブジェクト xxx 内で検索します。つまり、「xxx.name」を見つけようとします。
xxx 自体もオブジェクトなので、コンストラクター関数 (xxxObject() など) もあり、xxx.name が見つからない場合は、
xxxObject.prototype に行って見つけます。 . so ... 見つからなくなるまで深く掘り下げると、unknown が返されます。
いわゆるプロトタイプの継承は、単純な検索ルールにすぎません。
一方、aObj が特定のメンバーにアクセスできるようにする必要がある場合は、その (または aObj に似たインスタンス) プロトタイプ
を変更するだけで済みます。これは JavaScript で非常に一般的に使用されます。たとえば、すべての文字列に特定の属性を持たせたい場合:
String.protoype.MyName = 'string'
または、すべてのオブジェクトに特定の属性 (またはメソッドなど) を持たせたい場合)、次に:
Object.prototype.getMyName = function() {
return this.MyName;
}
なんとすばらしいことでしょう。String も getMyName を使用でき、関数も getMyName を使用できるようになり、すべてがなくなりました。名前にも名前があります。もちろん、名前内の文字
は未定義です。
名前はまだ名前です、あなたが哲学的狂人になるかどうかは考えもしませんでした。


5. 関数式
これは JavaScript の発明ではありません。その発明者は亡くなっており、彼の発明は今でも私たちを悩ませています...エジソンのランプと同じです。泡はまだ私たちを照らしています。
実際、関数型言語は命令型言語と同じくらい「完全な」言語実装ソリューションです。基本的な考え方はコマンド
の式と同じなので、このわかりにくい名詞を使いたくない場合は、C または Delphi に変更してください。言語は完全に異なります。そのため、ほとんどの
> 場合によっては、これらの伝統的で一般的な商用言語とも互換性がありません。
実際、あなたはそれを毎日使っています。
次のコード行には関数型言語のアイデアが満載です:
a b
本当ですか?実際、「 」記号を関数として考えると、まったく同じです。実際、いわゆる関数は実行プロセス、操作、関数エントリです。つまり、コード内の何かはデータまたは操作のいずれかです。そして、
それが操作である場合、それは「関数」と考えることができます。上記のコード行 - 式の中の a と b は明らかにデータであり、数値はそれに対して演算を実行する操作であるため、当然「関数、プロセス、または操作」とみなすことができます。つまり... 2 つの数値の合計を演算する「関数」は、次のように
で書くことができます:
func_add(a, b)
または次のように:
( a b)
それはすべて、テキストだけです。表記が異なるだけです。これは、私がこの記号を「jia」と言ったのに、あなたが「ande」だと主張し、別の
人が「a-d-d」と発音すると主張するようなものです。違いはありますか?いいえ。
すべてのプログラマは毎日、ステートメント、式、演算ロジックを作成します。これらのことは 1 つの...えっと...非常に大きな
関数で記述できること、または無数の小さくて見た目が美しい関数に分割できることは誰もが知っています。これらすべての関数を次々に実行すると、
は「関数型言語」になります。したがって、「関数型言語の祖」として知られる LISP は、次のように「関数型操作を接続する」言語です。

コードをコピー コードは次のとおりです。 🎜>

(defun subst (x y z)
(cond ((atom z)
(cond ((eq z y) x)
('t z)))
(' t (cons (subst xy (car z))
(subst xy (cdr z)))))


Some people think it is ugly spaghetti, while others think it is the simplest language. Oh, it's up to you, as long as you understand it, it doesn't matter what it looks like.
Since functional language only has continuously executed functions - it has no "statements" and must achieve logical integrity. Simply put, he
needs to implement the three basic logics of "sequence, branching and looping" in the process of continuous execution. The functional solution is to use ternary conditional operation
to replace if/then/else, which is the following code:
if a then b else c
// is equivalent to
a ? b : c
In addition, recursion (function calling function) is used to implement loops. Considering that recursive function calls will lead to stack overflow (Stack overflow at...),
so functional language proposes "tail recursion", that is, when writing code, "ensure" that only the last one in the function Recursive call during operation.
In this way, this recursive call does not need to retain the stack - because there are no subsequent operations, it can be optimized into a single line of
jmp assembly instructions that do not need to return.
The world is really beautiful. The so-called functional formula is just a bunch of operation entries, as well as jmp, jmp, jmp. But, but, isn't it - this CPU?
6. More advanced functional formula (1)
In fact, the world is not beautiful.
If a CPU is just lying there, it will only have instructions such as sequence, branch, and loop in it. But when it is running, there must be a
clock ticking... ticking... If it is multi-core, there will be several such things ticking at the same time.
This is the problem, the world is not originally a single time sequence, nor is it lawful. So there will be concurrency, interruptions, and exceptions. Functional language should
should extend infinitely like spaghetti. So when there are multiple ticks, should there be multiple spaghetti? But, in this case
is it still called spaghetti?
The solutions in functional expressions are called continuations and nodes. Continuation stops the current process and goes to another place and then returns; node ensures that the code at one location is independent and complete and has nothing to do with another node. In functional languages, multiple nodes are like parallel universes. In most cases, they are transparent to each other. If they want to connect, extremely huge energy and... a wormhole are needed.
We don’t need to delve into the issue of multiple nodes. The space-time issues caused by access in multiple spaces are issues studied by astronomers and space-time multi-dimensional theorists
. We only need to know: If you If there is a cross access relationship between multiple nodes, then the world/universe will be destroyed. Such instructions are written in white papers, reference manuals, and astronauts' daily guides for languages ​​like ErLang that natively support multiple universes. If you want to get to the root of the problem and think you have a clear understanding of more than 300 advanced numbers, physics and astronomy terms, here is an entry guide for programmers, you might as well start from Start here:

http://www.php.cn/
Continuation is one of the ways to solve the status problem. Simply put, when there is time, there is state: there is past, present and future. As for the past, we have history, and we will determine what happens now because of what happened in the past. For example, because we drank too much yesterday, we can only eat gruel today; and now is tomorrow's yesterday, so we must prepare for tomorrow. What can we do to record today’s status, for example, we have eaten porridge today; as for tomorrow, of course, there are many things that will happen, and we have to prepare one by one.
Oh, the important thing is to be "prepared". This is called an event in computer systems. Or call it a plan, or call it an emergency. Do you know why our PC can run? En... because there is an instruction pipeline that executes instructions in a sufficiently small time slice. For a computing system, this scheduled instruction access behavior is an interrupt. So one day a friend asked me: If the execution logic is only sequence, branch and loop, then what are the triggers in the process system? I thought about it for a long time and had no solution. Now to answer this question, we have to add the dimension of "time". The so-called burst, concurrency and similar things are the logic under the concept of timing.
Okay, when we "get ready" to prepare for triggering something in the future - simply put, just think of it as a clock handler (it's called OnTimer in Windows, and in browsers It is called setTimeout/setInterval). In order for us to make a spaghetti meal in functional language at this time, we explain: "We are already prepared" and "How prepared we are." According to the basic principles of functional style, a function has nothing to do with the state, and it has nothing to do with the timing of "the future". This has become a contradiction.
In fact, we have already had a head-on conflict with this contradiction once. This is the "cycle". Because the loop needs a state quantity to indicate the progress of the loop,
This "progress" is related to timing. The functional style uses "recursion" to solve it, that is, passing the progress through the parameters of the recursive function. On both sides of the "Recursive Parameters" interface, functional expressions are time-independent. The resulting problem is stack overflow, and the solution is tail recursion; the resulting problem is programming complexity, and whether it can be proven that tail recursion can replace all recursion; the solution is... Weinberg said Yes, all solutions to problems create new ones. Oh...it's Weinberg again. Now, we clearly need "more states" because we have the system running in one or more time series - that is, the CPU. Even if we have nodes and guarantee "no wormholes", then we still need to solve the past, present and future problems of a CPU.
The functional experts said two words: persistence. It's simple, just pass the past, present status, and preparations for the future as parameters of the function. It seems that "now" is about to explode, because it must include not only past and present states and changes, but also future operations. So the new solution is: if you want not to explode now, just don't do calculations on the "continuous" interface.
The operation is based on the "future" making decisions based on the "past" data. This is continuity. The functional feature that supports it is lazy evaluation. Simply put,
function f(x, c) {
...
c(x);
}
f(data, f);
Due to the transmission interface On f(), c itself is not evaluated, so the explosion will or will not occur when c(x) is operated in the future. If
there is a limit to the entropy of the universe, then this limit will also be in the unknown future. Moreover, in the unknown future, it is also possible that the distortion will return to the present. These are the two principles of
continuation:
---------------------
After a successful continuation, there is a new continuation (or process )
A failure will continue to return to the previous choice point
---------------------
It is precisely because there is a persistent state, and this The state and persistence itself are passed through function parameters, so "returning to the choice point" is only a decision for the future self
and has nothing to do with the current state.
7. More advanced functional expressions (2)
In any case, the complexity of various functional expressions does exist to maintain a kind of self-purity in the programming paradigm. For example, the problem of generator (generator)
is because there is a relationship between the generation of a batch of data (such as increment), and the generation process is timing related (not always obtained in one call
All data), so functional language defines a function concept such as "generator". We can define a yield in the generator.
This return is a wormhole from the "future" to the "now". Through this wormhole, we can get a time series related data. The following
is an example of this (Fibonacci sequence example on mozilla):


8. Conclusion
It seems, it seems that this "No Nonsense" article contains a lot of nonsense... Haha, just kidding, is it really completely free of nonsense, or can a living person read it?
If you really want to read No Nonsense, you should read college textbooks. Or, here is also a book "JavaScirpt Language Essence and Programming Practice".
Seeing wood, the essence of language..., haha.

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