为什么不 loadash/underscore 将 util 方法放在数组原型上?
why don't loadash/underscore put the util method on array prototype?
为什么 util 方法没有将 each
、map
等函数放在数组原型上?
下划线 _
让我的代码长了 位 ?不应该更整洁吗?
还是我漏掉了什么?
你得问问最初的 Underscore 开发者,但我能想到几个原因:
可枚举性问题
Underscore 于 2009 年首次发布时,第 5 版 JavaScript 规范 刚刚 出来,并没有得到广泛实施。正是该规范使得向对象添加 non-enumerable 属性成为可能;在那之前,向对象添加属性意味着它们出现在 for-in
循环中。这输出 "foo",例如:
Array.prototype.foo = function() {};
for (var k in []) {
console.log(k);
}
示例:
Array.prototype.foo = function() {};
for (var k in []) {
log(k);
}
function log(msg) {
var p = document.createElement('p');
p.appendChild(document.createTextNode(msg));
document.body.appendChild(p);
}
从 ES5 开始,可以改为这样做:
Object.defineProperty(Array.prototype, "foo", {
value: function() { }
});
...这使得 foo
属性 不可枚举 (不会出现在 for-in
循环等中) , 但同样,当 Underscore 出现时,那是全新的。
很多人使用 for-in
来遍历数组,尽管他们不应该没有安全措施。因此,与其破坏大量代码,他们决定不扩展内置原型。
冲突
即使没有可枚举性问题,在通用库中扩展内置原型也不一定是个好主意。 Underscore 可能想出的有用功能的任何名称都可能很容易被 TC-39 委员会在 JavaScript 的未来版本中使用,从而导致冲突。
清晰度
将它们放在 _
上可以清楚地表明您使用的是下划线,而不是 JavaScript 数组的内置功能。
对其他类型对象的实用性
许多 Underscore 方法适用于任何 类数组,而不仅仅是数组。使这些方法在 _
而不是 Array.prototype
上可用使得在非数组上使用它们更简单。例如,考虑 _.pluck
,它可以方便地用于 DOM 元素集合(类似于数组,但不是数组):
var values = _.pluck(document.querySelectorAll("input"), "value");
示例:
var values = _.pluck(document.querySelectorAll("input"), "value");
var p = document.createElement('p');
p.appendChild(document.createTextNode(values.join(", ")));
document.body.appendChild(p);
<input type="text" value="one">
<input type="text" value="two">
<input type="text" value="three">
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
为什么 util 方法没有将 each
、map
等函数放在数组原型上?
下划线 _
让我的代码长了 位 ?不应该更整洁吗?
还是我漏掉了什么?
你得问问最初的 Underscore 开发者,但我能想到几个原因:
可枚举性问题
Underscore 于 2009 年首次发布时,第 5 版 JavaScript 规范 刚刚 出来,并没有得到广泛实施。正是该规范使得向对象添加 non-enumerable 属性成为可能;在那之前,向对象添加属性意味着它们出现在 for-in
循环中。这输出 "foo",例如:
Array.prototype.foo = function() {};
for (var k in []) {
console.log(k);
}
示例:
Array.prototype.foo = function() {};
for (var k in []) {
log(k);
}
function log(msg) {
var p = document.createElement('p');
p.appendChild(document.createTextNode(msg));
document.body.appendChild(p);
}
从 ES5 开始,可以改为这样做:
Object.defineProperty(Array.prototype, "foo", {
value: function() { }
});
...这使得 foo
属性 不可枚举 (不会出现在 for-in
循环等中) , 但同样,当 Underscore 出现时,那是全新的。
很多人使用 for-in
来遍历数组,尽管他们不应该没有安全措施。因此,与其破坏大量代码,他们决定不扩展内置原型。
冲突
即使没有可枚举性问题,在通用库中扩展内置原型也不一定是个好主意。 Underscore 可能想出的有用功能的任何名称都可能很容易被 TC-39 委员会在 JavaScript 的未来版本中使用,从而导致冲突。
清晰度
将它们放在 _
上可以清楚地表明您使用的是下划线,而不是 JavaScript 数组的内置功能。
对其他类型对象的实用性
许多 Underscore 方法适用于任何 类数组,而不仅仅是数组。使这些方法在 _
而不是 Array.prototype
上可用使得在非数组上使用它们更简单。例如,考虑 _.pluck
,它可以方便地用于 DOM 元素集合(类似于数组,但不是数组):
var values = _.pluck(document.querySelectorAll("input"), "value");
示例:
var values = _.pluck(document.querySelectorAll("input"), "value");
var p = document.createElement('p');
p.appendChild(document.createTextNode(values.join(", ")));
document.body.appendChild(p);
<input type="text" value="one">
<input type="text" value="two">
<input type="text" value="three">
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>