3 回答

TA貢獻1898條經驗 獲得超8個贊
前言:像這樣的問題并不能真正表明某人是一個“好的”程序員,它只是意味著他們熟悉語言中的技巧,而這些技巧不會帶來更易于維護的代碼。對于經常使用此類技巧的公司或團隊,我會保持警惕。
(就我個人而言:當我還是 Microsoft 的 SE 時,我曾研究過 Chakra JavaScript 引擎,我喜歡認為我非常了解 JavaScript/ECMAScript,但我仍然需要思考很長一段時間如何在沒有使用prototype
或defineProperty
- 所以這就是為什么我認為如果他們期望得到直接答案,這不是一個好的技術面試問題- 但如果這是一個旨在提示你向面試官提問的面試問題,那么那就不同了)。
選項 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 );

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

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.
?*
?**/
添加回答
舉報