
数日前、
TheShockと
私は、JavaScript(アーキテクチャ、フレームワーク、問題)に関する質問を収集する
トピック を作成しました。 それらに答える時です。 コメントとメールの両方で多くの質問を受けました。 答えのこの最初の部分は、私が得た質問です。
1.プロトタイプの継承。 どのように機能しますか?
プロトタイプモデルの理解に問題があり、「古典的な」クラスに慣れていますが、JSを勉強することにしました。 可能であれば、パターンの形式で、「クラス」を構築するための可能なオプション、メソッドと変数の異なるレベルの可視性を説明する記事を書いてください。 そのような記事は膨大な数で見つかることを理解していますが、JSでは可視性のレベルは「必要ない」ことを理解しています。
答えは非常に長かったので、別のトピックを作成しました:
JavaScriptの基礎と誤解2.オブジェクトを作成するための最も便利なモデルは何ですか?
新規の場合、エラーからどのように保護されますか:
1.コンストラクター関数私は常に大文字で書きます。
2. FunctionNameのこのinstanceofを使用して作成の妥当性を確認します(パフォーマンス上の理由から、このinstanceof arguments.calleeを避けます)。
3. 2番目と似ていますが、ウィンドウで確認します。 名前をハードコーディングしたり、ブラウザ外環境用のスクリプトを記述したりしません。
より良く、より親しみやすく、イデオロギー的に新しいものを通してオブジェクトを作成します。 デザイナーは大文字にする必要があります。
私は規則に頼ることを好み、コンストラクター内でこれをチェックしません-私はコンストラクターを新しいものなしで呼び出したため、グローバルに飛んでいます-これは「愚か者自身」を意味します そして、決して私はnewでエラーを奨励しません-一部の人々はこれがグローバルなものであるかどうかを確認し、次にユーザーがnewなしでコンストラクタを呼び出し、コンストラクタ内にオブジェクトを作成してそれを返します-これはエラーとイデオロギー的に間違ったアプローチです。
var Obj = function () { "use strict"; this.pew = 100; };
newはファクトリメソッド、および短いコンストラクタには受け入れられません-jQuery
コードを要約します。
3. JSでどのマウスボタンが押されたかを判断する方法
mousedown mouseup
イベント
mousedown mouseup
すべてのマウスボタンによってトリガーされます。
click
は左のみです。 イベントハンドラーで、
event.button
ボタンのコードをチェックして、押されたボタンを見つける必要があります。
(0-左、1-中央、2-右)。 IE8では、すべてが間違っています。コードを参照してください。
var button = document.getElementById('button'),
jQueryはこのIEの欠陥を修正し、
event.button
の魔法の代わりに
event.which
をチェックする価値があり
event.button
$('button').mousedown(function (event) { alert(['Left', 'Middle', 'Right'][event.which]); });
例:
jsfiddle.net/azproduction/W2XgH詳細:
www.quirksmode.org/js/events_properties.html段落「どのマウスボタンがクリックされましたか?」
jQuery event.which:
api.jquery.com/event.which4.キーボードのキーストロークイベントをインターセプトすることはできますか?
ブラウザがその後ウィンドウをスクロールしないように、JavaScriptでキーボードのキーストローク(下矢印、上矢印)のイベントをキャプチャすることは可能ですか? 可能な場合、この動作のブラウザー間に機能はありますか? たとえば、画面全体に収まらないテーブルがありますが、線に沿って移動するにはキーボードの矢印を使用します。 ブラウザがページをスクロールしないことが必要です。
これを行うには、いわゆるデフォルトのアクションをキャンセルする必要があります:下矢印とマウスホイールでウィンドウをスクロールし、右マウスボタンでコンテキストメニューを表示し、
form.submit()
をクリックして
form.submit()
を実行します。入力をクリックすると、フォーカスが取得されます。ブラウザはリンクなどを介してアンカーに移動します。
jQueryを使用すると、次のように実行できます。
重要なポイントがあります。 defaultActionを実行する前に
preventDefault()
実行する必要があります。 たとえば、入力をクリックしたときにフォーカスを与えたくない場合は、defaultAction-mousedownが実行されるまで、チェーン内のイベントにハンドラーをハングさせる必要があります。
$('input').bind('mousedown', function (event) { event.preventDefault();
イベントのチェーン自体は次のとおりです。
1.マウスダウン
2.フォーカス(フォーカスの前に、別のオブジェクトでぼかしが機能します)
3. mouseup
4.クリック
イベントをフォーカス以下に絞ると、何も起こりません。 defaultActionは、マウスダウン後に機能します。
5.このキーがバインドされている場合、ESCを押したときにgifアニメーションを停止する問題を解決するにはどうすればよいですか?
上記の回答を参照してください。 一部のブラウザでは、Escキーを押すと、gifアニメーションが停止し、ページの読み込みが停止します-これはデフォルトのアクションです。
デフォルトアクション
event.preventDefault()
元に戻す必要があります。
$(document).bind($.browser.webkit ? 'keydown' : 'keypress', function (event) {
6.そして、クロージャーが作成された演算子()は何ですか?
括弧を使用すると、パーサーは関数の後の括弧の内容(グループ化演算子または関数呼び出し演算子)を理解できます。
このようにすると:
function () {
この場合、関数名がないためにSyntaxErrorが発生します(宣言関数には常に名前が必要です)。
名前を追加する場合:
function foo() {
2番目の場合、名前は(foo)に設定され、理論的には、関数宣言はうまくいくはずです。 ただし、まだ式エラーのないグループ化演算子に関しては、構文エラーがまだあります。 この場合、関数呼び出しブラケットではなく、関数宣言に続くのはグループ化演算子です!
ParseErrorを防ぐ方法は他にもあります-関数を式の状態にする、つまり これがまさに関数式であることをパーサーに示します。
TheShockから:
!function () {
含まれています。 jQueryで。 ローカルスコープを持つ1つのブロック内のすべてのコードを選択できます。 これにより、内部変数へのアクセスが高速化され、グローバルネームスペースを混乱させることができます。最も重要なことは、ミニファイヤによる圧縮の方が優れていることです。 habrahabr.ru/blogs/jquery/118564
材料
dsCode Subtleties ECMA-262-3に基づきます。 パート5.機能。 -「括弧について」という質問続きを読む :
kangax.github.com/nfe7. XHRでの転送コード
サーバーは、ajaxシステムでのユーザーのアクションに「alert( 'Boom !!!');」という応答を送信します。 クライアントでは、受信した応答がeval()を介して実行され、実行されます。 このデータ転送の名前は何ですか? これはJSONではなく、XMLではなく、HTMLではありません。
これには名前はありません。 実際、これは非常に悪いアプローチです。PHPコードをデータベースに保存し、毎回評価するのと同じくらい悪いです。 条件付きの非機密性に加えて、そのようなアーキテクチャには強力な一貫性があり、将来はやり直しが困難になります。 このようなモデルでは、データ+コード+表現などの混乱が発生します。何かをやり直すには、このもつれを解き、多数の接続を考慮して変更を加え、混乱させる必要があります。 私はそのような混乱から機能の一部を引き裂くことについて話していません...
コードサポートを簡素化するには、システムの各部分を最大限に分離し、接続数(依存関係)を減らす必要があります。 弱い接続を取得するために(アプリケーションの一部を可能な限り簡単に切り離したり交換したりできる場合)、イベントや、たとえばMVCアプリケーションアーキテクチャが導入されます。
読む:
そして再びMVCについてWebアプリケーションでのイベント駆動型モデルの適用Backbone.jsを使用した複雑なインターフェイスの作成8.スクリプト全体をハングさせることなく、コマンド実行のキューを遅延させて正しく整理する方法は?
JavaScriptには、コード自体が実行され、DOMツリーが再描画され、タイマーが機能する1つのスレッドがあります。 一連の操作(サイクル、重い機能)を実行するたびに、インターフェイスとのユーザーインタラクションがブロックされます(チェーンが重くない場合、ユーザーは変更に気づきません)。 UIのブロックを防ぐため、ThreedはJavaScriptにWeb Workersスレッドを導入しました。
ワーカーを使用できない場合は、サイクルと重い機能を最適化する必要があります。 Nicholas C. Zakasが著書OReilly High Performance JavaScriptに書いているように、UI Threedが100ミリ秒以下でブロックされた場合、ユーザーは遅延に気付かないでしょう。 つまり 100ミリ秒を計算できるので、ユーザーが遅延に気付かないようにUI Threedのロックを解除する価値があります。
以下は、彼の本のすべてのプロセッサー向けに最適化された元のコードです。
function timedProcessArray(items, process, callback) { var todo = items.concat();
timedProcessArray
関数は、25ミリ
timedProcessArray
UI
timedProcessArray
ブロックし、一連のアクションを実行してから、25ミリ
timedProcessArray
UI
timedProcessArray
解放します。
読む:
Nicholas C. Zakas-OReillyの高性能JavaScript
Comix Web WorkersWeb Workersを使用して計算WXHR:味のある古き良きXHR9.ユーザーがウィンドウのサイズ変更を完了したことをどうにかして知ることは可能ですか?
このようなイベントはありませんが、ユーザーがしばらくウィンドウのサイズを変更したかどうかを確認できます。これはonresizeendにほぼ対応しています。
コードスケッチ:
var time = 0, timerId, TIME_ADMISSION = 100;
実例:
jsfiddle.net/azproduction/2Yt6T10. window.open()を使用して、タブではなく新しいウィンドウを開く方法
この動作はブラウザ固有です。 Operaは常にタブを開きます(ただし、ウィンドウとして表示されます)。Safariは常にウィンドウを開きます(Safariの動作はバイパスできます)。 Chrome、FF、およびIEは制御可能です。
追加のパラメーター(ウィンドウの位置)を渡すと、新しいウィンドウが開きます。
window.open('http://www.google.com', '_blank', 'toolbar=0,location=0,menubar=0');
何も送信しない場合、タブが開きます:
window.open('http://www.google.com');
多くの場合、新しいタブを開く必要があります。サファリに問題がある可能性があります。デフォルトでは(設定に応じて)、サファリはwindow.open関数が呼び出されるたびに新しいウィンドウを開きます。 ただし、
Ctrl+Shift/Meta+Shift
ながらリンクをクリックすると、(設定に関係なく)常に新しいタブが開きます。 新しいタブを開くには、
Ctrl+Shift/Meta+Shift
て「クリック」イベントをエミュレートします。
function safariOpenWindowInNewTab(href) { var event = document.createEvent('MouseEvents'), mac = (navigator.userAgent.indexOf('Macintosh') >= 0);
11.効果的にディープコピーを作成する方法は?
oldObjectが変更されない場合、プロトタイプを介して複製する方が効率的です(非常に高速です)。
function object(o) { function F() {} F.prototype = o; return new F(); } var newObject = object(oldObject);
正直なクローン作成が必要な場合は、オブジェクトツリーを再帰的にたどり、いくつかの最適化を実行する方が高速です(これまでのところ、これが最速の正直なクローン作成アルゴリズムです)。
var cloner = { _clone: function _clone(obj) { if (obj instanceof Array) { var out = []; for (var i = 0, len = obj.length; i < len; i++) { var value = obj[i]; out[i] = (value !== null && typeof value === "object") ? _clone(value) : value; } } else { var out = {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { var value = obj[key]; out[key] = (value !== null && typeof value === "object") ? _clone(value) : value; } } } return out; }, clone: function(it) { return this._clone({ it: it }).it; } }; var newObject = cloner.clone(oldObject);
jQueryの場合、次を使用できます。
読む:
ベンチマークの正直なクローニング技術stackoverflowの主題に関する非常に長い議論12.アナログデストラクタ/ファイナライザの作成方法は? そして一般的に、オブジェクトの寿命を管理する方法は?
JavaScriptでは、オブジェクトへの最後のリンクが消えると、オブジェクトは削除されます。
var a = {z: 'z'}; var b = a; var c = a; delete az; delete a;
つまり 「デストラクタ」を使用すると、オブジェクトを完全に削除することはできません-内容を消去することしかできません。
13.バイナリデータを処理することは可能ですか? もしそうなら、どのように?
JavaScriptでは、すべての数値は文字列形式で使用するために提示され、バイナリデータを操作するための組み込みツールはありません。 2進数を扱うための
BinaryParser JavaScriptライブラリがあります:エンコード、デコード(コードは地獄です!)
ECMAScript 6+(strawman)にはStructTypeのドラフトがあります(これは、C ++などでおなじみの構造体です)。 バイナリファイルの操作を簡素化するために必要です。 将来的には次のようになります。
const Point2D = new StructType({ x: uint32, y: uint32 }); const Color = new StructType({ r: uint8, g: uint8, b: uint8 }); const Pixel = new StructType({ point: Point2D, color: Color }); const Triangle = new ArrayType(Pixel, 3); let t = new Triangle([{ point: { x: 0, y: 0 }, color: { r: 255, g: 255, b: 255 } }, { point: { x: 5, y: 5 }, color: { r: 128, g: 0, b: 0 } }, { point: { x: 10, y: 0 }, color: { r: 0, g: 0, b: 128 } }]);
donnerjack13589 ArtemS JavaScript型付き配列を使用してバッファーから読み取ることができますが、2進数を取得することはできません。
XMLHttpRequestレベル2では、バイナリファイルを送受信できます。
14.ある関数から別の関数のコンテキスト変数を変更する方法は?
1. smthでプライマーコンテキストオブジェクトへのリンクを提供できます。
2.プライマーコンテキストで生成された関数をsmth関数に渡す
var primer = function (){ var a, b, c, d, e = {}; smth(function () { a = 1; b = 2; c = 3; d = 4; }, e); alert([a, b, c, d, e.pewpew]); }, smth = function (callback, e) { callback(); e.pewpew = "pewpew"; }; primer();
3.以前(FireFox 3.6-)は__parent__を介してコンテキストに到達することが可能でしたが、バージョン4ではこの機能は削除されました。
15.記事「関数を呼び出す5つの方法」について。 これらのNの方法のうち、5つ目(記事4、コメント4、コメント数)のどれが適用すべきか、そしてその理由は?
グローバルコール/メソッドコールおよびコンストラクターは考慮しません。それらのスコープはすでに明確です。
私は電話で個別に住み、申請します。 それらは同じことをします-明示的なthisコンテキストで関数を呼び出します。
1.コンストラクターのオーバーライドを呼び出して適用します。
2.引数NodeListおよびその他の配列のようなオブジェクトを配列に変換し、ライブリスト(getElementsByTagName)を配列に変換します
3. Function.call.applyを使用してラッパーを作成するトリック:
任意の数の引数を使用して、指定されたコンテキストでbar()を呼び出すラッパーfoo()を記述する必要があります
ハイボルグから
従来の形式では、次のようになります。
function bar() {}
このサラダの代わりに、call.applyトリックを使用します。
function foo() { Function.call.apply(bar, arguments); }
これは次のように機能します:apllyは、fooに渡されたパラメーターを使用してbarオブジェクトでFunction.callを呼び出します。 つまり、コンテキストとarg1、arg2を使用した最初の例では、次のようになります。
bar.call(context, arg1, arg2)
4.
バインドエミュレーション
16.ある機能の実行範囲を別の機能に移す方法は?
まさか。 以前(FireFox 3.6-)、__ parent__を介してコンテキストに到達することは可能でしたが、バージョン4ではこの機能はカットされました。
17.直接参照、eval、および「use strict」なしでグローバルオブジェクトを正しく取得するにはどうすればよいですか?
条件の1つを省略した場合、またはグローバルスコープでのみ実行した場合、次のことができます。
18.イベントをインターセプトした後、javascriptで後で再起動することは可能ですか?
イベントには負荷がかからず、単なるイベント記述子です。 ただし、次のようにリンクをイベントハンドラに明示的に渡すことができます。
$('#smth').click(function onSmthClick(event){ if (smth) {
しかし、これは良い解決策ではありません。なぜなら まだやることがたくさんあります。 そして、ロジックは非常に紛らわしいです。
ロジックをやり直し、汎用ハンドラーを2つの部分に分割することをお勧めします。
$('#smth').click(function handler1(event) { if (smth) {
19.そして、あなたはjsであなたの参考書を書くとは思わなかった? JavaScriptの詳細な学習場所を教えてください。 本、チュートリアル?
多くのサイトと多くの本があり
ます、それらの一部は
ロシア語に翻訳
されました 。
20. JSで要素のページ上のすべてのクリックをインターセプトするにはどうすればよいですか? つまり、シングルクリックハンドラーを作成します
DOMツリーの一番下のオブジェクトにクリックイベントハンドラーを掛ける必要があります。要素上のすべてのクリックは「ポップアップ」します(
交通警官が路上での浮上を禁止している場合)。
21. jQueryなしでXHRを実行する方法は?
非クロスブラウザー機能:
function xhr(m,u,c,x){with(new XMLHttpRequest)onreadystatechange=function(x){readyState^4||c(x.target)},open(m,u),send()}
クロスブラウザー、わずかに長い:
function xhr(m,u,c,x){with(new(this.XMLHttpRequest||ActiveXObject)("Microsoft.XMLHTTP"))onreadystatechange=function(x){readyState^4||c(x)},open(m,u),send()}
使用法:
xhr('get', '//ya.ru/favicon.ico', function(xhr){console.dir(xhr)});
22.ファイルシステムの操作
JavaScriptを介したファイルシステムの操作、たとえばファイルの読み取りと書き込みについて学びたいと思いました。 ほとんどの教科書では、ファイルの操作が不要なブラウザーのJavaScriptについて説明していますが、たとえばサーバーアプリケーションやXULなどでは、これは必要ですが、ドキュメントはほとんどありません。
Habréでのファイルアップロードを含む、ファイルシステムでのクライアントの作業については、次のような記事があります。
HTML5 File API:サーバーへの複数のファイルのアップロード好みとダンサーを含むhtml5 File APIを使用してファイルをダウンロードするFileSystem APIとFile API:理解して使用する最短画像アップローダー!Node.jsサーバー上のファイルの操作に関する良い記事があり
ますNode.jsでのファイルの読み取りと書き込みXULについては、
MDC File_I / Oの記事を
ご覧ください。
23.リフロー、再ペイント、およびそれらを最小化する方法。
1.ブラウザが
requestAnimationFrame
関数をサポートしている場合、
setInterval/setTimeout
代わりにそれを使用する必要があり
setInterval/setTimeout
ブラウザは、同時に実行されるアニメーションを最適化して、リフローと再ペイントの回数を1回に減らすことができます。これにより、アニメーションの精度が向上します。 たとえば、JavaScriptのアニメーションは、CSS遷移またはSVG SMILと同期します。 さらに、アニメーションが非表示のタブで実行されると、ブラウザーは再描画を継続せず、CPU、GPU、メモリの使用量が少なくなり、その結果、モバイルデバイスのバッテリー消費が削減されます。
2.多数のフロート要素を避けます(リフローは減少します)
4.できるだけDOMツリーを変更します-メモリに書き込み、DOMに1回挿入します(リフローは減少します)
5.バンドル内のオブジェクトのプロパティを変更します(リフロー、再描画は減少します)(これは最新のブラウザーには当てはまりません)
6.絶対に配置されたオブジェクトのみでアニメーションを実行します(リフローは減少します)
7.要素のグループを変更する前に、
style.display = "none"
非表示にし
style.display = "none"
(リフローは減少します)(これは最新のブラウザーには当てはまりません)
トピック外ですが、最適化についても:8.イベントの委任を使用して、イベントの数を減らします。
9. DOM要素へのキャッシュ参照(セレクターの呼び出しが最もコストのかかる操作です)
10.クイックセレクター関数querySelectorAll()firstElementChildを使用します
11. document.getElementsByTagNameは要素の「ライブ」コレクションを返すことに注意してください(要素がDOMツリーに追加されると、コレクションは自動的にそれを受け取ります)
最近の多くのブラウザでは、これらの方法はそのような目に見える利点を与えません(ブラウザ開発者はすべてを最適化します)。
読む:
Nicholas C. Zakas-OReillyの高性能JavaScript
requestAnimationFrameを使用した高度なアニメーション24. childProcesses node.js - ?
オーバーヘッドが多すぎるため(これはApacheを使用したPHPのようなものです)、余分なメモリ、フォーク時間、初期化時間(jidコンパイル)、CPU負荷などを割り当てるため、各リクエストに対してchildProcessesを使用しないでください。Node.jsは負荷を非常によく分散し、アプリケーションのメインスレッドである「イベント処理ループ」で単一のプロセッサコアを読み込みます。Node.jsの理想的なダウンロードは、カーネルごとに1フォークです。Clusterを使用してフォークすることをお勧めします。クラスターはバランサー(マスター)として機能し、フォーク(スレーブ)になります。大量のリクエストに対するchildProcessesの使用は正当化されます。あなたはまだここで読むことができます:stackoverflow.com/questions/3491811/node-js-and-cpu-centric-requests25. node.jsでrunInNewContextを使用する
runInNewContext? —
node-js.ru/12-control-context-using-runinnewcontext, ( Node.js — nodester). , — , . : / — GC ( ). .
おわりに
TheShockは、この記事に記載されていないすべての質問に回答しますが、重いインターフェイス(gmailなど)のアーキテクチャに関する記事もあります。不明な点がある場合は質問してください。