Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 构建阵列侦听器_Javascript - Fatal编程技术网

Javascript 构建阵列侦听器

Javascript 构建阵列侦听器,javascript,Javascript,是否有一种方法可以将侦听器附加到另一个进程正在构建的数组,以便在array.length达到某个值时,侦听器执行回调并触发相应的代码 fooArray = []; // another code adds objects to array if (fooArray.length = 5) { // callback } else { // continue checking fooArray.length } 您必须使用自己的方法在数组中进行更改 Array.prototype.my

是否有一种方法可以将侦听器附加到另一个进程正在构建的数组,以便在array.length达到某个值时,侦听器执行回调并触发相应的代码

fooArray = [];
// another code adds objects to array

if (fooArray.length = 5) {
  // callback
} else {
  // continue checking fooArray.length
}

您必须使用自己的方法在数组中进行更改

Array.prototype.myPush = function () {

    this.push.apply( this, arguments );
    if ( this._binder && this._binder.test.call( this ) ) {
        this._binder.callback.call( this );
    }

}

Array.prototype.bind = function (tester, callback) {
    this._binder = {
        test: tester,
        callback: callback
    };
}

var arr = [4, 6, 9, 20];
arr.bind( function () {
    return this.length >= 5;
}, function () {
    console.log( "Array has exceeded" );
} );

arr.myPush( 40 );

好的,是和否。没有办法以100%安全的方式完成,因为JavaScript不支持运算符重载,这意味着您不能修改数组索引运算符的行为(
[]

但是,很少使用数组索引操作符将数组添加到。也就是说,这是一种非常罕见(但有效)的向数组添加项的方法:

var arr = [];
for( i=0; i<5; i++ ) arr[i] = i;
然后您可以相应地修改
push
方法:

arr.push = function() {
    var arr = this;
    Array.prototype.push.apply( arr, arguments );    
    arr._listeners.forEach( function(listener) {
        listener( { event: 'push', newLength: arr.length } );
    });
}
您几乎可以在事件对象中放入任何您想要的内容(如旧计数、添加的元素、时间戳等)

为了使此功能更加强大,您必须将此技术用于修改数组的所有其他
Array
方法,例如
pop
shift
,等等。请参见此处的
Array
的所有方法:

根据你的需要,你可以考虑其他的技术。例如,如果你做了大量的函数包(就像我们上面的代码>推< /COD>),你应该考虑某种面向方面的编程(AOP)框架。你也可以很容易地写自己的。例如,我们可以重新进行上述工作:

function after( f, after ) {
    return function() {
        f.apply( this, arguments );
        after.apply( this, arguments );
    }
}

var arr = [];
// convenience function for broadcasting an event
arr._broadcast = function( o ) { 
    this._listeners.forEach( function(listener) {
        listener( o );
    }
}

arr.push = after( arr.push, function() {
    this._broadcast( { event: 'push', newLength: arr.length } );
});
这种方法的优点是,可以更容易地扩展
数组的其他方法:

arr.pop = after( arr.pop, function() {
    this._broadcast( { event: 'pop', newLength: arr.length } );
});
等等

如果您需要能够制作许多这样的“广播”数组,那么正如前面提到的,您可以创建自己的自定义数组类型,扩展
array
,但是JavaScript为代码重用提供了比传统OOP更灵活的模式。因此,您不必创建扩展
数组的
事件数组
,而只需创建
数组的函数。prototype
将神奇地使该实例成为事件发射器:

Array.prototype.makeBroadcaster = function() {

    this._listeners = this._listeners || [];
    this._broadcast = function( o ) { 
        this._listeners.forEach( function(listener) {
        listener( o );
    }
    this.registerListener = function( listener ) {
        this._listeners.push( listener );
    }

    this.push = after( this.push, function() {
        this._broadcast( { event: 'push', newLength: arr.length } );
    }
    this.pop = after( this.push, function() {
        this._broadcast( { event: 'push', newLength: arr.length } );
    }
    this.shift = after( this.push, function() {
        this._broadcast( { event: 'shift', newLength: arr.length } );
    }
    // etc....
}
现在,每当您有一个数组要广播它发生了什么,您所要做的就是:

var arr = [];
arr.makeBroadcaster();
arr.addListener( function(evt) {
    console.log( "%s (new length: %d)", evt.event, evt.newLength );
} );
一些闭幕词:

  • 正如我在文章开头提到的,如果代码使用数组索引操作符修改数组,则无法引发该事件。具体来说,可以使用数组索引操作符“增长”数组。换句话说,如果数组包含5个元素,并且执行
    arr[9]=“hello”
    ,那么数组中现在将包含10个元素(其中5-8为
    未定义的
    )。没有办法检测到这一点,但以这种方式修改数组是非常罕见的

  • 您还可以使用
    length
    属性修改数组的长度。也就是说,如果您有一个十元素数组,并且您调用
    arr.length=5
    ,它将截断该数组,使其只有五个元素。这可能是通过重写
    length
    属性(使用
    Object.defineProperty
    )检测到的,但如果可能的话,这听起来非常危险。同样,以这种方式截断数组在JavaScript中非常少见

  • 如果事件确实必须100%准确,即使在上述情况下,那么,您最好能够创建您自己的对象,该对象具有基本的数组功能,如
    推送
    等。不过,这将非常尴尬,因为您必须实现类似于
    get(index)
    的功能,而不是使用更方便的数组索引操作符

下面是一个JSFIDLE演示了整个过程:


JavaScript不是很整洁吗?

错误:如果(fooArray.length==5)传递了回调函数吗?然后使用它:if(callback!=undefined&&typeof callback=='function')callback();不,没有。数组不会引发事件。有许多数据绑定框架以及小型发布/订阅库…可能会研究这些
Array.prototype.makeBroadcaster = function() {

    this._listeners = this._listeners || [];
    this._broadcast = function( o ) { 
        this._listeners.forEach( function(listener) {
        listener( o );
    }
    this.registerListener = function( listener ) {
        this._listeners.push( listener );
    }

    this.push = after( this.push, function() {
        this._broadcast( { event: 'push', newLength: arr.length } );
    }
    this.pop = after( this.push, function() {
        this._broadcast( { event: 'push', newLength: arr.length } );
    }
    this.shift = after( this.push, function() {
        this._broadcast( { event: 'shift', newLength: arr.length } );
    }
    // etc....
}
var arr = [];
arr.makeBroadcaster();
arr.addListener( function(evt) {
    console.log( "%s (new length: %d)", evt.event, evt.newLength );
} );