15 Stimmen

Arguments.callee Alternative in ES6 zur Bestimmung der aufrufenden Funktion

Im Framework, das ich entwickle, habe ich einen Mechanismus konstruiert, der es erlaubt, private und geschützte Eigenschaften und Methoden zu definieren.
Die einzige Möglichkeit, die ich in den ES5-Spezifikationen gefunden habe, um das zu tun, war die Verwendung von arguments.callee
so:

descriptor.method = function () {
    if (__callerIsProptected(arguments.callee.caller.caller, cls))
        return value.apply(this, __defaults(_.values(arguments), defaults));
    throw 'Versuch, die ' + access + ' Methode "' + cls._name + '::' + name + '" aufzurufen';
};

In Strict-Modus rufen Aufrufe von arguments.callee und arguments.caller Ausnahmen hervor. Gibt es bequeme Alternativen, um das zu tun?

Aktualisierung - hinzugefügter gesamter Funktionscode

   function __descriptor(cls, type, name, descriptor, access) {
    //protected private non-function descriptor.value is replaced by get/set pair
    if (access !== 'public' && type == 'property') {
        delete descriptor.value;
        delete descriptor.writable;
        _.isFunction(descriptor.get) || (descriptor.get = function () {
            return this.__get(name);
        });
        _.isFunction(descriptor.set) || (descriptor.set = function (value) {
            return this.__set(name, value);
        });
    }
    //remove uselesses
    if (_.isFunction(descriptor.get) || _.isFunction(descriptor.set)) {
        delete descriptor.value;
        delete descriptor.writable;
        if (!_.isFunction(descriptor.get)) {
            descriptor.get = function () {
                return this.__get(name);
            };
        }
        if (!_.isFunction(descriptor.set)) {
            descriptor.set = function (value) {
                return this.__set(name, value);
            };
        }
    } else {
        delete descriptor.get;
        delete descriptor.set;
    }
    if (descriptor.get) {
        var getter = descriptor.get;
        //mutate getter and setter if given respectively to access level
        if (access === 'public') {
            descriptor.getter = function () {
                return getter.apply(this, arguments);
            };
        } else if (access === 'protected') {
            descriptor.getter = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return getter.apply(this, arguments);
                throw 'Versuch, das ' + access + ' Eigenschaft "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.getter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return getter.apply(this, arguments);
                throw 'Versuch, das ' + access + ' Eigenschaft "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.getter._class = cls;
    }
    if (descriptor.set) {
        var setter = descriptor.set;
        //mutate getter and setter if given respectively to access level
        if (access === 'public') {
            descriptor.setter = function () {
                return setter.apply(this, arguments);
            };
        } else if (access === 'protected') {
            descriptor.setter = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return setter.apply(this, arguments);
                throw 'Versuch, das ' + access + ' Eigenschaft "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.setter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return setter.apply(this, arguments);
                throw 'Versuch, das ' + access + ' Eigenschaft "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.setter._class = cls;
    }
    if (descriptor.value !== undefined) {
        if (!_.isFunction(descriptor.value)) return descriptor;
        var value = descriptor.value;
        var defaults = descriptor.defaults || [];
        if (access === 'public' && type == 'method') {
            descriptor.method = function () {
                return value.apply(this, __defaults(_.values(arguments), defaults));
            };
        } else if (access === 'protected') {
            descriptor.method = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return value.apply(this, __defaults(_.values(arguments), defaults));
                throw 'Versuch, die ' + access + ' Methode "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.method = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return value.apply(this, __defaults(_.values(arguments), defaults));
                throw 'Versuch, die ' + access + ' Methode "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.method._class = cls;
    }
    return descriptor;
}

1voto

ThaFog Punkte 493

Einmal habe ich dasselbe Framework (veraltet) entwickelt und der einzige Weg, um in Strict-Mode einen Aufrufer herauszufinden, war tatsächlich eine Ausnahme zu werfen und den Aufrufer-Namen per RegExp aus dem Stack-Trace zu ermitteln. Soweit ich mich erinnere, war es nicht immer genau. Schauen Sie sich zum Beispiel den Code des caller-id Skripts an

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X