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.
*
**/
添加回答
举报