在javascript中创建自定义迭代“each”函数

时间:2013-11-30 11:23:26

标签: javascript

我正在尝试构建自己的对象并为其创建函数。我有以下对象,它从字符串中取出字母:

var Letters = function( word ) {
    this.letters = word.split('');
    this.length = this.letters.length;
    return this;
};

然后我创建了一个函数,允许将字母/字符串添加到 Letters 对象的实例中:

Letters.prototype.addLetter = function(toAdd) {
    for( var i = 0; i < this.length; i++ ) {
        this.letters[i] += toAdd;
    }
    return this;
};

我的问题是,当我尝试创建一个自定义的每个函数,它迭代 Letters 对象的一个​​实例时,我应用了方法 addLetter Letter 实例的当前迭代,我收到一条错误消息,指出当前迭代没有方法 addLetter

这是我到目前为止所写的:

Letters.prototype.each = function(callback){
    for( var i = 0; i < this.length; i++ ) {
        console.log(this.letters[i]);
        this.push(callback.call(this, this.letters[i], i));
    }
    return this;
};

我想传递的测试如下:

var test = new Letters('dude');
console.log('test1', test); //should return d, u, d, e

var test2 = test.addLetter('x');
console.log('test2', test2); //should return dx, ux, dx, ex

var test3 = test.each(function(e){
   e.addLetter('y');
});
console.log(test3);//should return dxy, uxy, dxy, exy

关于如何实现这一目标的任何想法? 感谢

这是代码的小提琴(打开控制台以查看结果):http://jsfiddle.net/cJqqb/

3 个答案:

答案 0 :(得分:1)

这部分:

callback.call(this, this.letters[i], i)

...说要调用callback函数将其this设置为this函数中的.each()Letter的实例callback ),并传递this.letters[i]两个参数ifunction(e){ e.addLetter('y'); } - 也就是说,传递数组中的当前项及其索引。到目前为止一切都那么好,因为每种方法通常都是如此。但是在你的回调中:

e

... this.letters[i]实际上是e - 一个字符串。因此.addLetter()没有var test3 = test.each(function(){ this.addLetter('y'); }); 方法。如果您将回调更改为如下所示,那部分将在“不工作”的意义上“起作用”:

this.push()

虽然您因使用this而收到错误,因为Letter.push()的实例且没有push()方法。如果你移除了.addLetter(),你会得到一些“有用”的东西:http://jsfiddle.net/cJqqb/1/

但是你会发现在循环中调用现有的.addLetter()是没有意义的,因为var test3 = test.each(function(v,i){ this.letters[i] += 'y'; }); 本身有一个循环。你可以这样做来获得预期的输出:

for

...但你会注意到这并不比使用.each()循环更好。问题是,尽管您的letters实现将当前i项的值传递给第一个参数中的回调,但您实际上无法对其进行修改,因为它是通过值而不是通过引用传递的字符串,所以要实际更改当前项目,你必须访问它所包含的数组,你可以从中为索引{{1}}的元素设置一个新值。

答案 1 :(得分:0)

this.lettersString的集合,而非Letters。因此,当您调用回调函数时,第一个参数将是一个字符串,而不是Letters的实例,因此未定义addLetter

var test3 = test.each(function(e){
    e.addLetter('y');  // e is a string! Try this.addLetter('y') instead
});

答案 2 :(得分:0)

e是一个字符串(this.letters数组中的一个项目),也就是说,内置String对象的一个​​实例,你试图调用{{1它上面的方法,由于addLetter不存在,显然会失败。也就是说,这是我对你的尝试的解释,希望它可以帮助:

String.prototype.addLetter

用法:http://jsfiddle.net/wared/WLt4L/

Bonus:这是Letters继承自Array的另一个演示:http://jsfiddle.net/wared/kEG56/(尚未经过深度测试)。