谁可以帮助解释这个JavaScript算法[] .filter.call()

时间:2016-11-10 15:47:33

标签: javascript arrays filter call

我有从string作为参数按顺序接收唯一元素的任务。我不明白这个函数 uniqueElements 如何返回['A','B','C','B']

var word = "AAAABBBBCCBB";
var uniqueElements = function(word) {
    return [].filter.call(word, (function(elem,index) {
        return word[index-1] !== elem
    }));
}    
uniqueElements(word);      
//it should return ['A','B','C','B']

我检查并阅读了以下来源:

MDN MozillaJS Blog但没有成功。

7 个答案:

答案 0 :(得分:2)

此处[].filter.call的目的是在字符串上应用filter方法。天真地你会先尝试这样做:

return word.filter(function(elem,index) {
    return word[index-1] !== elem;
});

... - 如果word是一个数组 - 会返回满足条件word[index-1] !== elem的字符(word[index-1] !== word[index]的缩写),即每个字符这与之前的角色不同。

但是,filter方法仅存在于从Array原型继承的对象上,而不是字符串的情况。

但是,filter本身可以处理类似数组的对象,即具有length且可能具有数字属性的对象。要在没有真正filter对象的情况下调用Array,可以在该函数上使用call,然后提供上下文(即类似数组的对象)作为第一个参数。其他论点保持不变。因此,您首先需要知道在哪里找到filter方法...它位于Array.prototype上,因此您可以像这样引用它:

Array.prototype.filter

但是由于所有数组都可以访问此方法,因此只需要一个空数组,并引用其filter方法:

[].filter

两者中的任何一个都可以。现在你必须对它执行call方法,并提供你想迭代的类似数组的对象:

[].filter.call(words, ...)

其余的就像你使用真正的数组:你提供回调函数:

return [].filter.call(word, function(elem,index) {
    return word[index-1] !== elem
});

返回值不再是字符串。它就像 - filter总是返回 - 一个数组:一个真正的 - 它是由filter方法创建的。

ES6方式:

在ES6中,您可以用更易读的方式编写它,因为现在有Array.from方法,它可以将类似数组的对象转换为真正的数组。然后您可以继续使用filter方法:

return Array.from(word).filter(function(elem,index) {
    return word[index-1] !== elem
});

传播运营商是ES6提供的另一种选择:

return [...word].filter(function(elem,index) {
    return word[index-1] !== elem
});

答案 1 :(得分:1)

它对数组对象上的filter方法执行显式call(),以便它们可以传入一个字符串。他们只是使用[]而不是Array,因为它的语法较短或有人试图在写作时变得聪明。

通常,filter()方法会影响数组自己的内容。但是,通过call(),你可以通过传入另一个数组来改变上下文,或者在这种情况下,传入一个字符串(被视为一个字符数组)。然后它为每个元素运行提供的函数,如果函数的返回值为true,则保留元素。

答案 2 :(得分:1)

var uniqueElements = function(word) {
    return [].filter.call(word, (function(elem,index) {
        return word[index-1] !== elem
    }));
}    

相当于

var uniqueElements = function(word) {
    return word.split("").filter(function(elem,index) {
        return word[index-1] !== elem
    });
}    

应该已经更清楚了:它将word转换为char数组,然后过滤掉与前一个不同的每个char。这解释了为什么" B"在结果中出现两次。

要获得独特元素,您可以

var uniqueElements = function(word) {
    var res = []
    word.split("").forEach(function(val){
        if (res.indexOf(val)===-1) res.push(val);
    });
    return res
}  

答案 3 :(得分:0)

如果您不了解代码的作用,您可以记录操作! IE

var word = "AAAABBBBCCBB";
function uniqueElements(word){
    return [].filter.call(word,(
        function(elem,index) { 
        console.log("Index : "+index+" | Elem : " +elem+" | CompareTo "+word[index-1]);
            return word[index-1] !== elem;
        }
    ));
}
uniqueElements(word); 

您将获得以下输入:

Index : 0 | Elem : A | CompareTo undefined
Index : 1 | Elem : A | CompareTo A
Index : 2 | Elem : A | CompareTo A
Index : 3 | Elem : A | CompareTo A
Index : 4 | Elem : B | CompareTo A
Index : 5 | Elem : B | CompareTo B
Index : 6 | Elem : B | CompareTo B
Index : 7 | Elem : B | CompareTo B
Index : 8 | Elem : C | CompareTo B
Index : 9 | Elem : C | CompareTo C
Index : 10 | Elem : B | CompareTo C
Index : 11 | Elem : B | CompareTo B

使用它,您可以检查每个不等于之前的元素是否都发送到您的数组。

很少有答案/评论已经指出[] .filter.call()如何运作。

如果您想获取String而不是数组,只需添加.join("") IE

即可
var word = "AAAABBBBCCBB";
function uniqueElements(word){
    return [].filter.call(word,(
        function(elem,index) { 
        console.log("Index : "+index+" | Elem : " +elem+" | CompareTo "+word[index-1]);
            return word[index-1] !== elem;
        }
    )).join("");
}
uniqueElements(word); 

答案 4 :(得分:0)

我已将代码拆分为带有内联注释的较小部分,以便更好地理解。

var word = "AAAABBBBCCBB";
var uniqueElements = function(word){
    // this is the filter function
    // this function will get each element of the string with its index
    var filterFunction = function(elem, index) {
        // the elements who pass the following condition are kept
        // the condition - 
        // if the character at the previous index (index-1) is not equal to the 
        // current element, then keep the element
        return word[index-1] !== elem;
    }

    // the below is equivalent to Array.prototype.filter.call(context, filterFunction)
    return [].filter.call(word, filterFunction);
}
console.log(uniqueElements(word));

答案 5 :(得分:0)

我会按照以下方式使用Array.prototype.reduce()做O(n)时间;

var str = "AAAABBBBCCBB",
uniques = Array.prototype.reduce.call(str, (p,c,i) => i-1 ? p[p.length-1] !== c ? (p.push(c),p)
                                                                                : p
                                                          : [c]);
console.log(uniques);

答案 6 :(得分:-1)



var word = "AAAABBBBCCBB";
var unique = word.split('').filter(function(item, i, ar) {
  return ar.indexOf(item) === i;
}).join('');