アンダースコアを付ける理由
最近、underscore.jsのソースコードを調べ始め、underscore.jsのソースコードの解釈を2016年の計画に入れました。
いくつかの有名なフレームワークライブラリのソースコードを読むことは、マスターと話すようなものであり、多くのことを学びます。なぜアンダースコアなのですか?主な理由は、アンダースコアが短く簡潔(約1.5k行)で、100以上の便利なメソッドをカプセル化し、結合が少なく、メソッドごとの読み取りに非常に適しており、元のポスターのようなJavaScript初心者に適しているためです。そこから、未定義の書き換えを回避するために未定義の代わりにvoid 0を使用するなどのいくつかのトリックだけでなく、変数タイプの判断、関数のスロットリングと関数のデバウンス、および多くのブラウザーの互換性などの一般的な方法も学ぶことができます。ハック、あなたはまた、作者の全体的なデザインのアイデアとAPIデザインの原則(後方互換性)を学ぶことができます。
後で、ホストはソースコードの読み取りで学んだ知識をあなたと共有するために一連の記事を書きます。
-
underscore-1.8.3ソースコード解釈プロジェクトアドレスhttps://github.com/hanzichi/underscore-analysis
-
アンダースコア-1.8.3ソースコードに関するフルテキストコメントhttps://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js
- Underscore-1.8.3ソースコード解釈シリーズの記事https://github.com/hanzichi/underscore-analysis/issues
ウォッチへようこそ〜(興味があれば、スター&ウォッチを歓迎します〜)あなたの注意は、ホストが書き続ける動機です
メイン
本日、オブジェクト関数のソースコード解釈部分が更新されました。
興味がある場合は、ホストの以前の解釈シリーズで、ソースコードのオブジェクト関数部分であるオブジェクトの拡張メソッドについて説明していることに気付くかもしれません。underscoreは、拡張メソッドを5つのタイプに追加します。つまり、オブジェクト->配列->コレクション->関数->ユーティリティです。これは、元のソースコード解釈シーケンスです(ソースコードシーケンスではありません)。その中には、Objectに38もの拡張メソッドがありますが、これはコードが多すぎることを意味するわけではありません。たとえば、2行のコードで複数のメソッドを処理できますが、前の記事で説明した_.isEqualメソッドには数百のメソッドが必要です。達成してもOKです。今日はオブジェクト関数セクションの最後の記事です。ホストが考えるいくつかの興味深いが説明されていないメソッドのソースコードを見てみましょう。(実際、多くのメソッドは使用が簡単で、実装も非常に簡単です。興味のある学生は自分でソースコードを入手できます)
_。ピック
まず、オブジェクトを渡し、オブジェクトのキーと値のペアを削除して、オブジェクトのコピーを返す_.pickメソッドを見てみましょう。
例を直接見てください。
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
=> {name: 'moe', age: 50}
_.pick({name: 'moe', age: 50, userid: 'moe1'}, ['name', 'age']);
=> {name: 'moe', age: 50}
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
return _.isNumber(value);
});
=> {age: 50}
一見すると、最初のパラメーターobjはオブジェクトであり、2番目のパラメーターは一連のキー値、配列(配列にはキーが含まれます)、または反復関数です。キー値または反復関数に従ってobjをフィルター処理します。新しいオブジェクトのコピーを返します。
私が設計する場合、おそらくパラメータに基づいてタイプを判断し、次にいくつかのif-elseを記述します。各if-elseブランチの内容は何の関係もありません。しかし、アンダースコアの記述は単純に素晴らしく、いくつかの状況を1つに変えます。
// 如果第二个参数是函数
if (_.isFunction(oiteratee)) {
keys = _.allKeys(obj);
iteratee = optimizeCb(oiteratee, context);
}
まず、if-elseは避けられません。渡された2番目のパラメーターがfunctionの場合、反復関数が渡されます。コンテキスト(this)に従って、新しい反復関数(optimizeCb)が返されます。この点はそれほど重要ではありません。ここでは選択的に無視できます)。
2番目のパラメーターが関数でない場合、次のキーは配列またはいくつかの連続する並列パラメーターである可能性があります。ここでは、アンダースコアで別の重要な内部メソッドであるflattenを使用します。その機能は、ネストされた配列を展開することです。このメソッドは将来分析します。ここでその機能を知ってください。
else {
// 如果第二个参数不是函数
// 则后面的 keys 可能是数组
// 也可能是连续的几个并列的参数
keys = flatten(arguments, false, false, 1);
// 也转为 predicate 函数判断形式
// 将指定 key 转化为 predicate 函数
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
また、着信反復関数と同じ形式に変換され、1つの方法で判断でき、2つの場合のkeys変数の意味が異なり、非常に賢いです。多くの場合、コードは冗長ですが、実際には、コードの能力が低すぎることが原因である可能性があります。これを行うことは考えられません。
_.create
_.createメソッドは非常に単純です。指定したプロトタイプといくつかの独自のプロパティに従って、返す新しいオブジェクトを作成します。
簡単な例を挙げてください。
var Person = function() {};
Person.prototype = {
show: function() {
alert(this.name);
}
};
var me = _.create(Person.prototype, {name: 'hanzichi'});
console.log(me);
// Object {name: "hanzichi"}
// name: "hanzichi"
// __proto__: Object
// show: function()
実際、me変数は、独自のプロパティとして名前を持ち、Person関数で構築されたオブジェクトです。
ブラウザがES5をサポートしている場合は、Object.create()を使用できます。
var Person = function() {};
Person.prototype = {
show: function() {
alert(this.name);
}
};
var me = Object.create(Person.prototype);
_.extendOwn(me, {name: 'hanzichi'});
console.log(me);
ES5がサポートされていない場合は、新しいコンストラクターを定義し、コンストラクターのプロトタイプを既知のプロトタイプ変数に割り当ててから、new演算子を使用してインスタンスを取得できます。
var Person = function() {};
Person.prototype = {
show: function() {
alert(this.name);
}
};
var _Person = function() {};
_Person.prototype = Person.prototype;
var me = new _Person();
_.extendOwn(me, {name: 'hanzichi'});
console.log(me);
アンダーコアの実現もほぼ同じです。
_.tap
もともとは_.tapの話をするつもりだったのですが、いきなりチェーンコールで話して穴を掘ったほうがいいと思いました。
概要
これで、オブジェクト関数部分のソースコード分析は終了です。具体的なコードについては、https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8を参照してください。 3.js#L901-L1269。コードのこの部分を読み終えましたが、真に理解して消化するには時間がかかります。私は約90%しか理解していないとしか言えません。議論と交換へようこそ。