为了账号安全,请及时绑定邮箱和手机立即绑定

Javascript面试题:让[1,2,3].sum()运行

Javascript面试题:让[1,2,3].sum()运行

叮当猫咪 2023-08-10 10:59:14
Javascript 面试问题: 在不使用和,的[1,2,3].sum()情况下运行精确的代码。PrototypeObject.definePropertyObject.defineProperties既然这是一个面试问题,我想有办法让它发挥作用吗?任何帮助/指示表示赞赏。谢谢
查看完整描述

3 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

前言:像这样的问题并不能真正表明某人是一个“好的”程序员,它只是意味着他们熟悉语言中的技巧,而这些技巧不会带来更易于维护的代码。对于经常使用此类技巧的公司或团队,我会保持警惕。

(就我个人而言:当我还是 Microsoft 的 SE 时,我曾研究过 Chakra JavaScript 引擎,我喜欢认为我非常了解 JavaScript/ECMAScript,但我仍然需要思考很长一段时间如何在没有使用prototypedefineProperty- 所以这就是为什么我认为如果他们期望得到直接答案,这不是一个好的技术面试问题- 但如果这是一个旨在提示你向面试官提问的面试问题,那么那就不同了)。


选项 1:全局错误处理程序:

这是一个可怕的方法:

window.addEventListener( 'error', function( e ) {

    

    if( e.error instanceof ErrorEvent || e.error instanceof TypeError ) {

        

        const msg = e.error.message;

        const suffixIdx = msg.indexOf( ".sum is not a function" );

        if( suffixIdx > -1 ) {

            const arrayStr = msg.substring( 0, suffixIdx );

            

            const arr = eval( arrayStr ); // <-- lolno

            const total = arr.reduce( ( sum, e ) => sum + e, 0 );

            console.log( total ); // 6

        }

    }

    

} );


[1,2,3].sum()

@NenadVracar 发布了一个简化版本eval,尽管它使用本地 ,但它避免了try:


try {

    [1,2,3].sum()

} catch (err) {

    const result = err.message

    .match(/\[(.*?)\]/)[1]

    .split(',')

    .reduce((r, e) => r + +e, 0)

    

  console.log(result)

}

选项 2:重写Array构造函数

如果您使用的是较旧的 JavaScript 引擎(2010 年之前创建的或 ECMAScript 5),则重写构造函数的脚本Array将在脚本遇到数组文字时使用该构造函数,并且.sum可以通过这种方式添加该方法:

Array = function() { // <-- THIS WILL NOT WORK IN BROWSERS MADE AFTER 2010!

    this.sum = function() {

        var total = 0;

        for( var i = 0; i < this.length; i++ ) {

            total += this[i];

        }

        return total;

    };

};


let total = [1,2,3].sum();

console.log( total );

选项 3:偷偷摸摸地处理财产prototype

正如其他人在评论中提到的,如果您将这些成员作为字符串访问,您仍然可以改变prototype成员或使用:Object.defineProperty


Array[ 'proto' + 'type' ].sum = function() {

    var total = 0;

    for( var i = 0; i < this.length; i++ ) {

        total += this[i];

    }

    return total;

};


let total = [1,2,3].sum();

console.log( total );


查看完整回答
反对 回复 2023-08-10
?
浮云间

TA贡献1829条经验 获得超4个赞

我们能在多大程度上绕过这里的界限?

假设我们希望下面的行起作用,[1, 2, 3].sum();那么我们可以很容易地让它做一些事情。请注意,由于自动分号插入规则,您所拥有的不一定是数组。它可能是带有逗号运算符的数组访问

({3: {sum: () => console.log(6)}}) //<-- object


[1,2,3].sum(); //<-- array access

或者为了更清楚,这里是等效的代码:


const obj = {

  3: {

    sum: () => console.log(6)

  }

};


obj[3].sum(); //<-- array access

因为,我没有看到应sum该做什么的定义,所以上面涵盖了列出的所有要求 - 没有原型恶作剧,没有额外的属性。

好吧,从技术上讲,sum没有总结任何东西,但这里有一个解决方法:像这样定义它

sum: (a, b) => a + b

现在,从技术上讲,它是一个将两个数字相加的函数。毕竟,不需要对1, 2, 3调用之前出现的序列求和。sum


查看完整回答
反对 回复 2023-08-10
?
繁花不似锦

TA贡献1851条经验 获得超4个赞

或者为了更清楚,这里是等效的代码:


const obj = {

  3: {

    sum: () => console.log(6)

  }

};


obj[3].sum(); //<-- array access

将其作为披萨/表情符号示例向您展示的目的是您可以解决此类测试。

当然,前面的代码可以简化为另一个更严重的代码片段,这也满足了使用 提出的问题的目的__proto__

[3]['__proto__']['sum'] = () => { console.log('this runs!, answer is 6'); };

[1,2,3].sum();


/**

 * Here am using `__proto__` instead 

 * of `Prototype`, they are both almost the same 

 * but `__proto__` works for instances only.

 *

 **/


查看完整回答
反对 回复 2023-08-10
  • 3 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信