ホームページ > 記事 > ウェブフロントエンド > フロントエンドを改善する必要があります。コードはどの程度悪くなる可能性がありますか? _html/css_WEB-ITnose
! KissyUI は、淘宝網のフロントエンド プロジェクト Kissy のグループです。会社のイントラネットで私の「悪いコードを読むシリーズ」を見た後、Long Zang はグループ内で次のように尋ねました。
そうです、悪いコードとは具体的に何ですか?これは、別のネチズンが gtalk で私に尋ねた質問を思い出します。彼は、3 つの条件 a、b、c がすべて真の場合は偽である必要があり、すべてが偽の場合は偽である必要があると判断します。
次に、KissyUI グループの学生は多くの答えを出しました:
[javascript] view plaincopy
// 4. 質問者自身の考え
(a + b + c) % 3
この問題は js で発生するため、弱い型の問題があります。つまり、a、b、c は整数または文字列などである可能性があるため、(a+b+c)%3 道路はそうではありません。利用可能なので、
回答答 答 答
(!! A+!! B+! !c)%n
var args=arguments, argn=args.length;
🎜 args[0] = !args[0]; 🎜 🎜 for (var i=1; i
[javascript] view plaincopy
この小さなコードには、splice/slice の使用が含まれています。スプライスは引数を操作するため、関数エントリで「特異な」変更が発生する可能性があり、異なるエンジンでのパフォーマンスへの影響に一貫性がなく、スライスでは 2 倍のデータ コピーが発生する可能性があります。ここでスライス() が依然として使用されている理由は、結局のところ、これは単なる関数パラメーターであり、「非常に大きな」配列ではないため、ストレージの問題を過度に考慮する必要がないためです。
次に、args で取得するものは配列であるため、for ループを使用するのは実際にはそれほど現代的ではありません。フロントエンドで軽蔑されない、正しく人気のあるスタイルは次のとおりです:
[javascript] view plaincopy
// v2.1 、v2 の詳細な分解
function e_xor(a) {
var args = [].slice.call(arguments,1);
var callback = function(b) ) {
if (!b != ! a) return true
}
[javascript]
view plaincopy
//v2.2, for v2 の最適化による !a 操作の数を減らす
function e_xor(a) {
return (a=!a, [].slice.call(arguments,1)).some(function(b) { if (!b != a) return true });
このコード行では、連続操作が使用されます。
( a=! a, [].slice.call(arguments,1))さて、今から v3 バージョンを書き始めます。なぜ? v2 バージョンはまだ十分にクールではないため、v2 バージョンでは Array.some() が使用されています。js1.6 で拡張されたこの機能はあまり「機能的」ではなく、オブジェクト指向の痕跡がいくつかあります。関数型言語の熱心なファンとして、私は「配列の列挙」のような問題に対する最も一般的な解決策は再帰であると信じています。
なぜですか? Erlang のような純粋な関数型言語では、Array.some() というアイデアは思いつきません。もちろん、そのようなメソッドはありますが、「より純粋な」観点から見ると、自分で記述する必要があります。ふふ。この種の「純粋な再帰」を js で行うにはどうすればよいでしょうか?おおよそのプロトタイプは次のようになります:
[javascript] view plaincopy
http://bbs.51js.com/viewthread.php?tid=85325
簡単に言えば、継続とは関数に対して継続的にコールバックを実行することです。パラメーター 。この機能は、新しい関数型言語パラダイムでサポートされています。この記事のこの例では、分析するために別のバージョンを作成しました。私はこれを tail() メソッドと呼んでいます。これは、関数パラメーターの末尾を指定することを意味し、関数 Function のプロトタイプ メソッドとして設計されています。
[javascript]
view plaincopy
Function.prototype.tail = function() { return this.apply(this, [].slice.call(arguments,0 ).concat( [].slice.call(this.arguments, this.length)));
[javascript]
view plaincopy
function foo(a, b) { alert([arguments.length, argument.callee] .length]);
[javascript]
view plaincopy
Function.prototype.tail = function() {
return this.apply( // 関数自体を呼び出します
this, // を使用しますfunction foo 自体をこの Object として扱う[javascript]
view plaincopy
// v3.1、tail() を使用したバージョン
function e_xor(a, b) {
if (argu ments.length == 引数.callee.length) return !a != !b;Arguments.callee.length は、仮パラメータの数を決定するためにここでも使用されます。つまり、再帰の終了条件は、パラメータ a と b の 2 つだけが残っており、tail() 部分をスキャンする必要がないということです。もちろん、戻り値の 3 項式の右半分 (?:) も再帰を終了します。この場合、別の条件が見つかりました。
この例では、末尾再帰関数として e_xor() を作成しましたが、この末尾再帰は関数型スタイルの本質です。残念ながら、その最適化は js ではサポートされていません。うわぁ~~ 後でリソースをチェックして、新しい Chrome v8 がサポートしているかどうかを確認します。クラスメイト v8、まだ V5 が必要ですか? :)
前のセクションで、Guy の問題解決のアイデアを見てきました。しかし、このレベルでは、多くの場合、抽象化の最初のステップが最も重要です。簡単に言えば、v3は次のとおりです
このフレームワークの抽象化自体に問題がある可能性があります。正しい理解は、「a、b は排他的論理和である」ではなく、「a は他の要素と排他的論理和である」です。したがって、v4 のフレームワーク抽象化は次のようになります。
[javascript]
function e_xor (a ) { .. v3では毎回bの値を後続部分に渡す必要があるため、tail()内で配列の結合concat()を行う必要があります。ただし、v4 のフレームワークを使用すると、b の値自体が後続の部分で暗黙的に保持されるため、結合する必要がありません。このように、tail() には新しい書き方が追加されました。実際、これは tail() の本来の意図に沿ったものです。スプライシング処理がある場合は、tail() ではなく foo() で処理する必要があります。 ) ) を処理します。
[javascript]
view plaincopy
}
v4 でのコードの記述はより簡単になります。
//v4.1、v3 よりも単純な実装
if (arguments.length < 2) return false;
if (!arguments[1] != !a) return true;
return argument.callee.tail();
問題: ガイには階級がない
tailed() の使用法は非常に簡単です:
[javascript] view plaincopy
簡単に言うと、tailed() のオペランドとして xor 関数を使用できます。その核心は、xor に似た一連の関数を公開することであり、開発者は次のプログラミング パラダイムを使用して操作を実装できます。例:
[javascript] view plaincopy
[javascript] View plaincopy
これで、tailed と呼ばれる半成熟したオープン ライブラリができました。いわゆる半成熟しているのは、tailed() にまだ次のコード行のような小さな欠陥があるためです。 .length +1) return false;
中央の f.length+1 の「1」は、xor によるデータの処理方法に関連する条件パラメーターです。簡単に言うと、a と argument[1] を比較する必要があるため、ここで +1 が必要になるのです。アルゴリズムが複数のオペランドを比較する必要がある場合、tailed() は汎用ではありません。したがって、正しく完全な末尾を使用すると、呼び出し元が終了条件を指定できるようになります。例:
使用されるメソッドは次のとおりです:
[javascript] プレーンコピーを表示
さまざまな操作では、less_one() を他の終了条件にすることができます。
さて、この解決策では、Guy には tailed ライブラリで十分ですか?いいえ。不倫には後がないと言われており、不倫する人によって不倫のやり方は様々です。たとえば、上記のコードには問題があることがわかります。つまり、tailed() には多くのレベルの関数クロージャがあり、呼び出し時に効率とストレージ スペースが不必要に消費されることを意味します。それで、何ができるでしょうか?例えば?あはは、パラダイム プログラミングに参加してテンプレートを作成できます:
view plaincopy
私たちは「それほど悪くないコード」を探しているのではないでしょうか?そうであれば、a、b、c の 3 つの操作条件を判断する最良の方法はおそらく次のとおりです。 )
または、a、b、c の型を考慮すると:
[javascript]
(!a!= !b || !a! =!c)
オペランドのセットを判断する状況を考慮する場合、それを配列として扱い、次のように記述します:
[javascript] view plaincopy
function e_xor(a) {
for (var na=!a,i=1; i if (!arguments[i] != na) return true } return false;
- 明確で明確な呼び出しインターフェイスを設計する、