重写jQuery .val()函数生效,但getter被多次调用
问题原因分析
你遇到的两次输出“Getter”的问题,根源在于jQuery原生的<select>元素val() getter内部逻辑会调用选中<option>的val()方法——你重写的val()方法是全局生效的,所以在执行$('select').val()时会触发两次:
- 第一次是直接调用select的
val()getter,进入你的重写方法打印“Getter”; - 第二次是原生select的
val()逻辑内部,遍历选中option并调用其val()方法,再次进入你的重写方法打印“Getter”。
解决方案
以下两种方案都能解决重复打印问题,同时保留你需要的核心功能:
方案一:仅针对目标元素生效
让自定义逻辑和调试打印只作用于.myselect类的select元素,其他元素直接走原生方法:
const originalVal = $.fn.val; $.fn.extend( { val: function() { // 仅处理.myselect类select的setter逻辑 if ( arguments.length > 0 && this.is('select.myselect') ) { console.log( 'Setter' ); const result = originalVal.apply( this, arguments ); this.trigger( 'change' ); return result; } // 仅在.myselect类select的getter时打印调试信息 if ( arguments.length === 0 && this.is('select.myselect') ) { console.log( 'Getter' ); } // 所有其他情况直接调用原生val方法 return originalVal.apply( this, arguments ); } } );
方案二:排除option元素的调试打印
如果你需要保留对所有元素的getter打印,只需排除option元素触发的重复输出:
const originalVal = $.fn.val; $.fn.extend( { val: function() { if ( arguments.length > 0 ) { if ( this.hasClass( 'myselect' ) ) { console.log( 'Setter' ); const result = originalVal.apply( this, arguments ); this.trigger( 'change' ); return result; } return originalVal.apply( this, arguments ); } // 排除option元素的getter打印 if ( !this.is('option') ) { console.log( 'Getter' ); } return originalVal.apply( this, arguments ); } } );
内容的提问来源于stack exchange,提问作者Gavin
相关产品推荐
相关产品推荐

