在MooTools中,什么'implement和.protype之间的区别是什么

In MooTools, what's the difference between .implement and .prototype

本文关键字:protype 之间 是什么 区别 implement MooTools 什么      更新时间:2024-04-02

实现更改原型,那么为什么不直接用"some class".prototype目录更改它呢…,它似乎非常无用或palaver

有两个方面需要实现。在类上下文和对象(Types/Natives)上。

共同利益

它们之间的共同点是,它们是API。因为它是API,MooTools可以添加一些方法来确保您不会(意外)覆盖在各种原生类型上受保护的原型方法。请参阅此位,它强制保护许多本机方法: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()由Class使用,请参见下文。

这并不意味着你不能做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() 拥有特殊方法

它还支持类突变体-您应该检查这一点,但它能够定义可以修改构造函数的特殊键,而不仅仅是添加到原型中。

再一次,你可以很容易地做到:

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;
}

正如你所看到的,这里面肯定有一些额外的逻辑。例如,您似乎可以为keyvalue传递具有相应属性名称的对象,使其实现在一个调用中向对象原型添加多个内容。

我会使用implement(),避免直接将东西添加到原型链中,除非你非常确定自己知道自己在做什么。毫无疑问,这些额外的东西是有原因的。