Câu hỏi phỏng vấn Javascript: make [1,2,3] .sum () run

Nov 17 2020

Javascript phỏng vấn câu hỏi: làm cho [1,2,3].sum()mã chạy chính xác mà không sử dụng PrototypeObject.defineProperty, Object.defineProperties.

Vì nó là một câu hỏi phỏng vấn nên tôi cho rằng có những cách nào để làm cho nó hoạt động?

Bất kỳ sự trợ giúp / hướng chỉ nào được đánh giá cao.

Cảm ơn

Trả lời

8 Dai Nov 17 2020 at 03:09

Lời nói đầu: Những câu hỏi như thế này không thực sự cho thấy ai đó là một lập trình viên "giỏi", nó chỉ có nghĩa là họ đã quen thuộc với các thủ thuật trong ngôn ngữ không dẫn đến mã dễ bảo trì hơn . Tôi sẽ cảnh giác khi làm việc cho một công ty hoặc nhóm thường xuyên sử dụng các thủ thuật như thế này.

(Và trong trường hợp cá nhân của tôi: Tôi đã làm việc trên công cụ JavaScript Chakra khi tôi là một SE tại Microsoft và tôi muốn nghĩ rằng tôi biết JavaScript / ECMAScript rất tốt và tôi vẫn phải suy nghĩ rất lâu về cách có thể thực hiện điều này mà không có sử dụng prototypehoặc defineProperty- vì vậy đó là lý do tại sao tôi không nghĩ rằng đây là một câu hỏi phỏng vấn kỹ thuật tốt nếu họ mong đợi một câu trả lời thẳng - nhưng nếu đây là một câu hỏi phỏng vấn nhằm thúc đẩy bạn đặt câu hỏi cho người phỏng vấn thì điều đó lại khác).


Tùy chọn 1: Trình xử lý lỗi chung:

Đây là một cách kinh khủng :

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 đã đăng một phiên bản đơn giản hóa để tránh eval, mặc dù nó sử dụng cục bộ try:

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

Tùy chọn 2: Ghi đè hàm Arraytạo

Nếu bạn đang sử dụng một công cụ JavaScript cũ hơn (được tạo trước năm 2010 hoặc ECMAScript 5) thì một tập lệnh ghi đè phương thức Arraykhởi tạo sẽ có phương thức tạo đó được sử dụng khi tập lệnh gặp một ký tự mảng và .sumphương thức có thể được thêm theo cách đó:

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

Phương án 3: Quay lén prototypetài sản:

Như những người khác đã đề cập trong các nhận xét, bạn vẫn có thể thay đổi prototypethành viên hoặc sử dụng Object.definePropertynếu bạn truy cập các thành viên đó dưới dạng chuỗi:

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

6 VLAZ Nov 17 2020 at 03:26

Chúng ta có thể xếp hàng ở đây bao nhiêu?

Giả sử rằng chúng ta muốn dòng sau hoạt động [1, 2, 3].sum();thì chúng ta có thể rất dễ dàng chỉ cần làm cho nó làm điều gì đó . Lưu ý rằng do các quy tắc chèn dấu chấm phẩy tự động , không nhất thiết bạn phải có một mảng. Nó có thể là quyền truy cập mảng với toán tử dấu phẩy trong đó.

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

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

Hoặc để làm rõ hơn, đây là mã tương đương:

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

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

Vì, tôi không thấy định nghĩa về những gì sumnên làm, những điều trên bao gồm tất cả các yêu cầu được liệt kê - không có tai quái dạng protoype, không có thuộc tính bổ sung.

OK, về mặt kỹ thuật, sumkhông tổng hợp bất cứ điều gì, nhưng đây là một cách giải quyết: hãy xác định nó như thế này

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

Về mặt kỹ thuật, nó là một hàm tính tổng hai số. Không có yêu cầu tính tổng chuỗi 1, 2, 3xuất hiện trước khi gọi sum, sau cùng.

2 LuisLimas Nov 17 2020 at 03:06

Đây là một cách:

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

Về mặt kỹ thuật, bạn không sử dụng Prototype, bạn đang sử dụng __proto__. Wich giống với một tên khác ... (nhưng chỉ dành cho các trường hợp)