使用原型就地修改数组

Modify an Array in-place with prototype

我创建了一个自定义原型,用于清理数组以便删除重复项排序。它有效并且看起来像这样:

 // given an example array such as this.
var names = [ 'Lara', 'Lucy', 'Alexa', 'Vanessa', 'Lucy', 'Brianna', 'Sandra' ];

Array.prototype.clean_up = function(){
    var
        set = []
    ;
    this.forEach(function(item){
        if ( set.indexOf(item) === -1 ) {
            set.push(item);
        }
    });

    set.sort();

    return set;
};

我唯一的抱怨是我不得不这样称呼它:

names = names.clean_up();

如果我可以像下面那样调用它,我会更喜欢它,比如 Array.sort()(我相信这被称为就地实现)。你怎么能那样做?

names.clean_up();

编辑:(显然,这属于此处而不属于答案)

我目前的解决方案如下,但感觉有点无效。我想知道是否可以做得更好。

Array.prototype.clean_up = function(){
    var
        set = [],
        self = this
    ;
    this.forEach(function(item){
        if ( set.indexOf(item) === -1 ) {
            set.push(item);
        }
    });

    set.sort();

     // reset and re-fill.
    while (this.length > 0) {
        this.pop();
    }

    set.forEach(function(item){
        self.push(item);
    });
};

对一个无效,对另一个无效:mentioned 已经有好几次您不应该修改原始数组。这是为什么?

我的意思是,如果有像 Array.sort() 这样的函数,那么它表明该语言能够做到这一点,并且 一些 实现似乎是 "okay"?为什么 sort() 可以,但自定义函数不行?

如果你想就地影响数组,你应该寻找重复项并从数组中拼接它们。 Array.prototype.indexOf 可以与第二个参数一起使用以从当前元素搜索并删除重复项,例如

Array.prototype.clean = function (){
  // Iterate backwards over array
  this.reduceRight(function(acc, value, index, arr) {
    // If first index of value isn't current index, remove this element
    if (arr.indexOf(value) != index) arr.splice(index, 1);
  }, null);
  // Now sort
  this.sort();
  // Return for chaining
  return this;
}

var arr = 'aztatffgff'.split('');
console.log(arr.join());
console.log(arr.clean().join());

向前遍历一个数组是行不通的,因为当拼接元素时,元素会被打乱顺序,因此会跳过下一个元素。您也不能只使用 filter 创建一个数组,因为您不能将该新数组分配给 this.

reduceRight 可以替换为 for 循环。