最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript interview question: make [1,2,3].sum() run - Stack Overflow

programmeradmin6浏览0评论

Javascript interview question: make [1,2,3].sum() exact code run without using Prototype and Object.defineProperty, Object.defineProperties.

Since it was an interview question I am assuming there are ways to make it work?

Any help/pointing direction appreciated.

Thanks

Javascript interview question: make [1,2,3].sum() exact code run without using Prototype and Object.defineProperty, Object.defineProperties.

Since it was an interview question I am assuming there are ways to make it work?

Any help/pointing direction appreciated.

Thanks

Share Improve this question edited Nov 16, 2020 at 20:26 gen_Eric 227k42 gold badges303 silver badges342 bronze badges asked Nov 16, 2020 at 19:54 serkanserkan 7,1514 gold badges42 silver badges50 bronze badges 7
  • @Dai not really going to work - an array literal will not just lookup Array in the scope chain (that's what new Array() would do) - it actually goes and initialises a native array, regardless of what occupies window.Array. – VLAZ Commented Nov 16, 2020 at 19:58
  • Did you sign a non-disclosure and agree not to share the interview questions? – anthumchris Commented Nov 16, 2020 at 19:59
  • @VLAZ Previously (like, before 2010) browsers would use a user-provided Array constructor when it encounters literals. JavaScript array literals are not initialized by the parser/piler but when encountered. – Dai Commented Nov 16, 2020 at 19:59
  • 1 What are the actual constraints? You aren't allowed to do anything with prototypes or you aren't allowed to use prototype as the property, or you aren't allowed to use the word "prototype"? Or what? – VLAZ Commented Nov 16, 2020 at 20:09
  • 1 I mean.. the correct answer they are looking for could be "there is no (good) way to do this" perhaps to see if you're willing to give something hacky vs. put your foot down – CrayonViolent Commented Nov 16, 2020 at 20:31
 |  Show 2 more ments

3 Answers 3

Reset to default 9

Preface: Questions like these don't really show someone is a "good" programmer, it just means they're familiar with tricks in the language that do not lead to more-maintainable code. I'd be wary of working for a pany or team that regularly uses tricks like this.

(And in my personal case: I worked on the Chakra JavaScript engine when I was an SE at Microsoft and I like to think that I know JavaScript/ECMAScript very well and I still had to think a long time about how this could be done without using prototype or defineProperty - so that's why I don't think this is a good technical interview question if they expected a straight-answer - but if this was an interview question that's meant to prompt you into asking questions of the interviewer then that's different).


Option 1: Global error handler:

Here's a horrible way:

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 has posted a simplified version that avoids eval, though it uses a local try:

try {
    [1,2,3].sum()
} catch (err) {
    const result = err.message
    .match(/\[(.*?)\]/)[1]
    .split(',')
    .reduce((r, e) => r + +e, 0)
    
  console.log(result)
}

Option 2: Override Array constructor

If you're using an older JavaScript engine (made prior to 2010 or ECMAScript 5) then a script that overrides the Array constructor will have that constructor used when the script encounters an array literal, and the .sum method could be added that way:

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 );

Option 3: Being sneaky with the prototype property:

As others have mentioned in the ments, you could still mutate the prototype member or use Object.defineProperty if you access those members as strings:

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 );

How much can we skirt the lines here?

Assuming that we want the following line to work [1, 2, 3].sum(); then we can very easily just make it do something. Note that due to the automatic semicolon insertion rules, it's not necessary what you have there to be an array. It might be array access with ma operator in it.

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

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

Or to make it more clear, here is the equivalent code:

const obj = {
  3: {
    sum: () => console.log(6)
  }
};

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

Since, I don't see a definition of what sum should do, the above covers all the requirements listed - no protoype shenanigans, no extra properties.

OK, technically, sum doesn't sum anything, but here is a workaround: define it like this

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

Now, it's technically a function that sums two numbers. There is no requirement to sum the sequence 1, 2, 3 that appears before calling the sum, after all.

Use pizza, no Prototype needed

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论