【问题标题】:Getting invalid formal parameters获取无效的形式参数
【发布时间】:2009-08-28 21:18:48
【问题描述】:

这是一个 SO 挑战

我想知道有人如何在没有arguments 对象的函数中获得无效的形式参数,以模拟不知道参数解构赋值的格式。这不是 ECMAScript 问题,仅与 JavaScript 有关。

您的mySolution 无法访问argumentstest。您将获得一个包含参数名称的 args 数组。您必须返回一个对象,该对象具有每个参数的属性,该参数是传递给函数的参数。简而言之,results[prop] 必须 === test[prop]。您的解决方案不应依赖错误或安全漏洞,因为它们将来可能不会出现。我想到的这个问题的解决方案不依赖于任何错误。

(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        // put your solution here

        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
            if (results[prop] !== test[prop])
                pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

这是我会接受的两种可能的解决方案之一:

(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        var i = args.length;
        while (i--) {
            results[args[i]] = eval("function::" + args[i]);
            // function::[args[i]] won't work unless you eval() it
        }

        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
            if (results[prop] !== test[prop])
                pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

该解决方案通过使用默认的 function:: 命名空间和 eval() 范围来工作。

例如:foo.function::barfoo.function::['bar'] 是同一事物 foo.bar

【问题讨论】:

  • 我什至不知道你可以定义这样的函数:function f({a, b, c})!这是怎么回事?
  • @nickf:这是JavaScript 1.7 解构任务的一部分。
  • 我不太了解'function::'这件事。会很高兴阅读有关此的内容。顺便说一句,很棒的问题。
  • Ashish:你会很难处理它,因为它没有在任何地方记录。哎呀,我想我是唯一一个在 MDC 上做过这么多事情甚至提到它的人。 E4X 规范中没有提到 function:: 命名空间。它的主要用途是向 XML.prototype 添加方法。 XML.prototype.x = myFunc 不起作用,但 XML.prototype.function::x = myFunc 起作用。
  • Ashish:如果您想了解更多信息,我有一篇关于 JavaScript 1.6+ 中的属性命名空间的博文,您可能想阅读:eligrey.com/blog/post/namespacing-properties-in-javascript

标签: javascript parameters


【解决方案1】:

100 分


(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        // put your solution here
        var getEscUnicode = function(str) {
            var ret = "";
            for(var j = 0; j < str.length; j++) {
                var temp = parseInt(str.charCodeAt(j)).toString(16).toUpperCase();
                for(var i=0; i < 5 - temp.length; i++) {
                    temp = "0" + temp;
                }
                ret = ret + "\\u" + temp;
            }
            return ret;

        }
        for(var i = 0; i < args.length; i++) {
            results[args[i]] = eval(getEscUnicode(args[i]));
        }
        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
                if (results[prop] !== test[prop])
                        pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

【讨论】:

  • 恭喜,您实际上找到了应对挑战的两种可能解决方案之一!您的解决方案依赖于我认为的错误,因此如果明天之前没有人找到其他解决方案,我会将其标记为已接受的答案。
【解决方案2】:

在 FireFox 3.0.13 中测试通过! 我通过更改 Object 原型“作弊”:

<html>
<head>
<title></title>
<script>
(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        // put your solution here
        Object.prototype._hasOwnProperty = Object.prototype.hasOwnProperty;
        Object.prototype.hasOwnProperty =
function(prop) {
 results[prop] = this[prop];
 return this._hasOwnProperty(prop);
}

        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
                if (results[prop] !== test[prop])
                        pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

</script>
</head>
<body>
<!-- Put the body of your page below this line -->

<!-- Put the body of your page above this line -->
</body>
</html>

这算不算?我想应该不会吧。 =p

【讨论】:

  • 也在 IE7 中测试过,但脚本根本不起作用(即使我删除了我的解决方案并仅使用提供的代码)
  • 这不算数,但它确实是一个创造性的解决方案!我想我将不得不将results 变为null 到:P
  • 既然我通过了测试,我是否至少能获得一票以防其他人获得投票? ;)
【解决方案3】:

家庭作业?这里有一个提示:使用eval

【讨论】:

  • 不,这不是家庭作业。不,您不能 eval("var") 获取 var 参数的值。
  • 如果这不是家庭作业,那么为什么要对可以访问哪些变量或可以使用哪些函数进行奇怪的限制呢?明确说明您的需求。
  • 可以使用 eval,只是你不能使用 eval,因为它没有帮助。
  • 此外,还有一个 one 限制,而不是多个限制。一个限制是你不能访问arguments
【解决方案4】:

我只能想到一种方法来实现这一点,甚至一种方法依赖于两者 - 已弃用的 callee.caller 和已经修复的 eval 的 FF 特性能够在指定函数的上下文中执行代码。

有趣的是,我认为 eval 在引入 function({...}){} 扩展之前已“修复”,但我并不完全确定。

我稍微减少了测试用例,但当然保留了一个实际的想法。

我首先尝试从调用者本身访问arguments,但看起来&lt;fn&gt;.arguments 在函数上下文中引用了与arguments 相同的对象; nulling arguments 对象本质上也被arguments 属性引用的对象破坏了。

我还考虑过从错误对象评估堆栈字符串(以获取 test 值),但这并不能解决任何问题,因为测试值是对象,而不是原语。

(function () {
  function mySolution () {
    var test = arguments = null;
    return eval('test', (function(){ return arguments.callee.caller; })());
  };
  var test = {
    "var"   : {},
    "this"  : {},
    "function": {},
    "if"    : {},
    "return"  : {},
    "true"  : {}
  },
  results = mySolution(test),
  pass = true;

  for (var prop in test)
    if (test.hasOwnProperty(prop))
        if (results[prop] !== test[prop])
            pass = false;

  alert(pass ? "PASS" : "FAIL");
})();

【讨论】:

  • arguments.callee.caller 上次我检查时没有被弃用,只是非标准。弃用的东西是arguments.caller。不过,您的解决方案并不能解决我的问题中所述的挑战。我的问题涉及实际获取形式参数的值(即function(a){return a} 获取a 形式参数)。
  • 另外,请测试您的解决方案,因为它实际上不适用于非固定或固定的 JS 引擎。给定someFunction(它声明了一个私有变量a),eval("a", someFunction) 不返回私有变量"a"。如果属性存在,则返回someFunction.a
  • 它确实有效,是的,我确实对其进行了测试。您在说哪些“非固定或固定 JS 引擎”?我还没有看到调用eval('a', someFunction) 时返回someFunction.a 的实现,所以我不知道你从哪里得到它。另一方面,Mozilla 有扩展来评估给定函数范围内的代码(即使用函数的内部 [[Scope]])参见bugzilla.mozilla.org/show_bug.cgi?id=442333
  • 好吧,你仍然没有抓住重点。即使这确实解决了它,我也出于某种原因取消了test,因此您无法访问它。如果您的解决方案在参数中使用解构赋值 ({a,b,c}),我会将其作为答案。
【解决方案5】:

啊哈!这次我找到了更好的答案。 (不过,我不得不承认我从 kangax 的回答中得到了大致的想法)。在 FF 3.0.13 中测试通过:

<html>
<head>
<title></title>
<script>
(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        // put your solution here
        var o = eval('arguments', mySolution)[0];
        for(var prop in o) {
         results[prop] = o[prop];
        }

        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
                if (results[prop] !== test[prop])
                        pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

</script>
</head>
<body>
<!-- Put the body of your page below this line -->

<!-- Put the body of your page above this line -->
</body>
</html>

【讨论】:

  • 我不太确定为什么会这样......看起来 eval() 函数可能对“arguments”属性有一个特殊情况,它不使用与在方法本身中使用?或者也许被赋值为“null”的“参数”实际上不是方法参数数组?
  • 我在 firefox 3.5.2 中测试过,但它不起作用“TypeError: eval('arguments', mySolution) is null”
  • 这似乎是 FF 中的一个错误,在以后的版本中修复 =(
  • 正如我已经解释过的,这是 Mozilla 中一个相当严重的安全漏洞(能够在任意函数范围内评估字符串)。 3.0.13 仍然“有效”(正如 RMorrisey 指出的那样),但 3.5 已经没有了。我认为他们在 3.0 之后不久就修复了它。
【解决方案6】:

尝试#3;再次,在 FF 3.0.13 中测试 PASS

<html>
<head>
<title></title>
<script>
(function () {
    function mySolution ({
        var,
        this,
        function,
        if,
        return,
        true
    }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null,

        args = ['var', 'this', 'function', 'if', 'return', 'true'],
        results = {};

        // put your solution here
        var o = mySolution[0];
        for (var prop in o) {
           results[prop] = o[prop];
        }

        return results;
    };
    var test = {
        "var"     : {},
        "this"    : {},
        "function": {},
        "if"      : {},
        "return"  : {},
        "true"    : {}
    },
    results = mySolution(test),
    pass = true;

    for (var prop in test)
        if (test.hasOwnProperty(prop))
                if (results[prop] !== test[prop])
                        pass = false;

    alert(pass ? "PASS" : "FAIL")
}());

</script>
</head>
<body>
<!-- Put the body of your page below this line -->

<!-- Put the body of your page above this line -->
</body>
</html>

【讨论】:

    【解决方案7】:

    尝试了很多方法。有点放弃了。但是如果你不能破坏系统,就改变系统。 我的解决方案:

    
    (function () {
        function mySolution ({
            var,
            this,
            function,
            if,
            return,
            true
        }) {
            // prohbit reference to arguments and the test object
            var test = arguments = null,
    
            args = ['var', 'this', 'function', 'if', 'return', 'true'],
            results = {};
    
            // put your solution here
    /********** MY SOLUTION STARTS ******************/
            return null;
        }
        function mySolution ({
            var,
            this,
            function,
            if,
            return,
            true
        }) {
            // new function does not prohbit reference to arguments and the test object
            //var test = arguments = null,
    
            args = ['var', 'this', 'function', 'if', 'return', 'true'],
            results = {};
            for(var i =0; i < args.length; i++) {
                results[args[i]] = arguments[0][args[i]];
            }
    /********** MY SOLUTION ENDS ******************/
            return results;
        };
        var test = {
            "var"     : {},
            "this"    : {},
            "function": {},
            "if"      : {},
            "return"  : {},
            "true"    : {}
        },
        results = mySolution(test),
        pass = true;
    
        for (var prop in test)
            if (test.hasOwnProperty(prop))
                    if (results[prop] !== test[prop])
                            pass = false;
    
        alert(pass ? "PASS" : "FAIL")
    }());
    

    【讨论】:

    • 当然arguments[0] 有对象,但挑战的全部目的是看看你是否可以在不复制解构的情况下获得无效参数。
    • 嘿,你能告诉我如何解决这个问题吗!
    【解决方案8】:
    (function () {
        function mySolution ({ var, this, function, if, return, true }) {
        // prohbit reference to arguments and the test object
        var test = arguments = null, args = ['var', 'this', 'function', 'if', 'return','true'], results = {};
        //LAME...
        };
        mySolution=function(a){var results=a;
        //LAME...
        return results;
    };
    var test = {
          "var" : {},
          "this" : {},
          "function": {},
          "if" : {},
          "return" : {},
          "true" : {} }, results = mySolution(test), pass = true;
     for (var prop in test)
            if (test.hasOwnProperty(prop))
                if (results[prop] !== test[prop]) pass = false;
     alert(pass ? "PASS" : "FAIL") }());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-16
      • 2012-11-21
      • 2020-04-16
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多