javascript - es6 中用于确定调用函数的 arguments.callee 替代方案

标签 javascript ecmascript-6 arguments

<分区>

在框架中,我正在开发,我已经构建了允许定义私有(private)和 protected 属性和方法的机制。
我在 ES5 规范中发现唯一的能力是使用 arguments.callee
像这样:

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

至于在严格模式下调用 arguments.callee 和 arguments.caller 导致抛出异常,是否有任何方便的替代方法来做到这一点?

更新 - 添加了整个被调用的函数代码

    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 'Attempt to get ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.getter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return getter.apply(this, arguments);
                throw 'Attempt to get ' + access + ' property "' + 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 'Attempt to set ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.setter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return setter.apply(this, arguments);
                throw 'Attempt to set ' + access + ' property "' + 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 'Attempt to call ' + access + ' method "' + 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 'Attempt to call ' + access + ' method "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.method._class = cls;
    }
    return descriptor;
}

最佳答案

有一次我正在开发相同的框架(已放弃),在严格模式下找出调用者的唯一方法是实际抛出异常并从堆栈跟踪中获取 RegExp 调用者名称。据我所知,它并不总是精确的。例如查看 caller-id 的代码脚本

关于javascript - es6 中用于确定调用函数的 arguments.callee 替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22589732/

相关文章:

javascript - 在同一个项目中混合 CommonJS 和 ES6 模块

javascript - 我可以控制 ES6 forEach 循环中的循环次数吗

python - 传递带有 "implicit"参数的函数

linux - 规避脚本中的参数列表太长(for 循环)

javascript - Jquery 获取公共(public)父级中输入元素值的数组

javascript - 有没有办法设置一个条件,使一个参数根据另一个参数而不同? JavaScript

import - 在 webpack.config 中使用 ES6 import 和 export default

javascript - JS 如何让 <main> 元素在页面加载时聚焦

javascript - 视频Javascript、HTML5、效果

linux - 如何创建不带参数 $1 和 $2 的字符串=$*