es6中用于确定调用者函数的arguments.callee替代方案[重复]

Posted

技术标签:

【中文标题】es6中用于确定调用者函数的arguments.callee替代方案[重复]【英文标题】:arguments.callee alternative in es6 for determining caller function [duplicate] 【发布时间】:2014-04-30 15:34:01 【问题描述】:

在框架中,我正在开发、构建机制,允许定义私有和受保护的属性和方法。 我在 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;

【问题讨论】:

使用这个的代码是什么样子的? 添加了描述符方法列表。根据访问级别和类型准备属性描述符:属性/方法 相关答案:***.com/questions/9777905/… 【参考方案1】:

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

【讨论】:

以上是关于es6中用于确定调用者函数的arguments.callee替代方案[重复]的主要内容,如果未能解决你的问题,请参考以下文章

ES6中箭头函数与普通函数this的区别

ES6箭头函数this指向

JavaScript ES6 箭头函数 匿名函数 普通函数

es6数组的方法

执行路径特定断点

ES6新增-箭头函数与普通函数的区别