変更プロトタイプを実装するので、ディレクトリを「いくつかのクラス」.prototype ...で変更しないのはなぜですか、それは非常に役に立たないか、またはパレーバーのようです
2 に答える
実装する側面は 2 つあります。クラス コンテキストおよびオブジェクト (タイプ/ネイティブ)。
共通の利点
それらの間の共通点は、それらが API であることです。MooTools は API であるため、さまざまなネイティブ型で保護されているプロトタイプ メソッドを (誤って) 上書きしないようにする方法を追加できます。多くのネイティブ メソッドの保護を強制するこのビットを参照してください: https://github.com/mootools/mootools-core/blob/master/Source/Core/Core.js#L238-282
また、implement はオーバーロードされています。つまり、プロトタイプの呼び出しごとに中断して改行するのではなく、同時に複数のメソッドを実装するオブジェクトを渡すことができます。
クラスの関数メソッドはラップされます。
これらのデコレータが利用可能です:
Function.implement({
hide: function(){
this.$hidden = true;
return this;
},
protect: function(){
this.$protected = true;
return this;
}
});
これは、あなたができることを意味します
Obj.implement({
foo: foo.hide(),
bar: bar.protect()
});
.hide()
これにより、ラップされていないプロパティを追加することで、ラップされていないメソッドを持つことができます。
Number.prototype.$family = function(){
return isFinite(this) ? 'number' : 'null';
}.hide();
.protect()
クラスによって使用されます。以下を参照してください。
これは、できないという意味ではありませんNumber.prototype.$family = somethingElse
。できるのです。
クラスの仕様
クラス コンストラクターで使用する場合は、 への参照と呼び出しにimplement
注意してください。$hidden
wrap()
var implement = function(key, value, retain){
if (Class.Mutators.hasOwnProperty(key)){
value = Class.Mutators[key].call(this, value);
if (value == null) return this;
}
if (typeOf(value) == 'function'){
if (value.$hidden) return this;
this.prototype[key] = (retain) ? value : wrap(this, key, value);
} else {
Object.merge(this.prototype, key, value);
}
return this;
};
これは、関数を渡すと、自動的にラップされることを意味します。ラッピングにより、.protect()
デコレーターを介してプライベート メソッドを使用したり、.hide()
Class Mutators もサポートしています。これを確認する必要がありますが、プロトタイプに追加するだけでなく、コンストラクターを変更できる特別なキーを定義する機能です。
繰り返しますが、簡単に行うことができます:
ClassConstructor.prototype.foo = someFn;
そして、これはうまくいきます。
// but:
ClassConstructor.prototype.foo = someFn.protect();
// however...
instanceOfClassconstructor.foo(); // works also.
これを参照してください:
// generic method.
var foo = function() {
console.log('hi');
};
var ClassConstructor = new Class({});
// implement the foo method as private.
ClassConstructor.implement({
foo: foo.protect()
});
var instance = new ClassConstructor();
// try to call it, will throw.
try {
instance.foo();
}
catch(e) {
console.warn(e);
}
// do it directly on the prototype
ClassConstructor.prototype.foo = foo.protect();
var instance2 = new ClassConstructor();
instance2.foo(); // works.
MooTools のソースを確認するか、コンソールで MooTools オブジェクトを調べて、implement()
呼び出されたときに内部で何を行っているかを確認できます。
MooTools 1.4.5 では、次のようになっています。
function (key, value){
if ($type(key) == 'object'){
for (var p in key) this.implement(p, key[p]);
return this;
}
var mutator = Class.Mutators[key];
if (mutator){
value = mutator.call(this, value);
if (value == null) return this;
}
var proto = this.prototype;
switch ($type(value)){
case 'function':
if (value._hidden) return this;
proto[key] = Class.wrap(this, key, value);
break;
case 'object':
var previous = proto[key];
if ($type(previous) == 'object') $mixin(previous, value);
else proto[key] = $unlink(value);
break;
case 'array':
proto[key] = $unlink(value);
break;
default: proto[key] = value;
}
return this;
}
ご覧のとおり、そこには間違いなく追加のロジックがあります。たとえば、対応するプロパティ名を持つオブジェクトを渡して、1回の呼び出しでオブジェクトプロトタイプに複数のものを追加して実装させることができるようkey
ですvalue
。
自分がimplement()
何をしているのかをよく理解している場合を除き、プロトタイプ チェーンに直接追加することは避けます。その余分なものには理由があります。