Javascript +eval(名称)+“];”; } } //将最终索引设置为具有该值 eval(name+“=\”+$(this.val()+“\”;”); }); //构建动态下拉列表 selectElements[0]=$.dynamicDropdown.buildSelectDropdown(数据); prepareDropdown(selectElements[0],this,0,“”; }).hide(); }; })(jQuery);
Javascript +eval(名称)+“];”; } } //将最终索引设置为具有该值 eval(name+“=\”+$(this.val()+“\”;”); }); //构建动态下拉列表 selectElements[0]=$.dynamicDropdown.buildSelectDropdown(数据); prepareDropdown(selectElements[0],this,0,“”; }).hide(); }; })(jQuery);,javascript,jquery,html,arrays,Javascript,Jquery,Html,Arrays,(函数($) { $.fn.dynamicDropdown=函数(选项){ 变量设置={ “分隔符”:“»”, “类名”:“, “级别”:[ {'markup':{dd},'class':false,'id':false,'disabled':false}, {'markup':“{dd}” ] }; $.extend(设置、选项); 返回$(this).each(函数(){ //原始下拉元素 var main下拉菜单=$(此); var defaultSelection=false; var级
(函数($)
{
$.fn.dynamicDropdown=函数(选项){
变量设置={
“分隔符”:“»”,
“类名”:“,
“级别”:[
{'markup':{dd},'class':false,'id':false,'disabled':false},
{'markup':“{dd}”
]
};
$.extend(设置、选项);
返回$(this).each(函数(){
//原始下拉元素
var main下拉菜单=$(此);
var defaultSelection=false;
var级别={};
//在标记中插入下拉列表,最后将其放入DOM中,附加事件等。
var insertSelectDropdown=函数(dd、级别、同级、位置){
var markup=settings.levels[level]&&settings.levels[level]。markup?settings.levels[level]。标记:“{dd}”;
//要支持将下拉列表放置在容器内和不放置容器的标记,
//有必要使用一些愚蠢的dom魔法
var container=$(''+settings.levels[level].markup.replace('{dd}',$('').append(dd.addClass('ddlevel-'+level)).html())+'').children()['insert'+position](同级);
var select=container.parent().find('select.ddlevel-'+级别)。removeClass('ddlevel-'+级别);
if(settings.levels[level]['class']){
选择.addClass(settings.levels[level]['class']);
}
if(settings.levels[level].id){
选择.attr('id',settings.levels[level].id);
}
如果(设置。级别[level]。已禁用){
选择.prop('disabled','disabled');
}
返回select.data('level',level.).data('container',container.).data('levels',dd.data('levels')).change(updateDropdowns);
}
//为选择元素生成标记
var buildSelectDropdown=函数(选项,选中){
var select=$('').data('levels',options);
//添加选项
$.each(选项、函数(索引、值){
var选项=$('').html(索引);
如果(类型(值)!=“对象”){
期权价值;
}
如果(已选择&&index==已选择){
option.attr('selected','selected');
}
选择。追加(选项);
});
返回选择;
};
//每次选择输入值更改时运行的事件函数
var updateDropdowns=function(){
var current=$(this.children(':selected').html();
var options=$(this.data('levels')[当前];
//非对象表示这是行的结尾,请设置值
if(typeof(options)!=“object”){
mainDropdown.val($(this.val());
}
否则{
//删除刚更改的dds之后的所有dds
var dd=$(本);
而(dd.data('next')){
dd=dd.data(“下一步”);
dd.data(“容器”).detach();
}
变量级别=$(此).data('level')+1;
//添加新的dds
$(this).data('next',insertSelectDropdown(buildSelectDropdown(options,defaultSelection[level]),level,$(this).data('container').last(),'After').change());
}
};
//从初始下拉列表生成级别
mainDropdown.children().each(函数()){
var options=$(this.html().split(settings.delimiter);
如果($(this).is(“:selected”)){
默认选择=选项;
}
var级别=级别;
对于(变量i=0;i
导致该问题的原因是dynamicDropdown
代码使用以下语法类型迭代数组:
for (prop in array)
它包括数组的所有iterable属性,而不仅仅是数组元素。在您的例子中,这将包括添加到数组中的associate
方法,因为它是可编辑的,这将导致问题
有关迭代数组的参考,请参阅
这是一个典型的例子,解释了为什么数组永远不应该使用for(数组中的prop)
语法进行迭代,而是
for (var i = 0; i < array.length; i++)
或者更现代:
for (item of array)
这也是一个典型的例子,说明了当您直接向数组.prototype
添加内容时所冒的风险
您可以通过不扩展
数组的原型来解决这个问题
(function($)
{
$.fn.dynamicDropdown = function(options) {
var settings = {
"delimiter" : " » ",
"className" : "",
"levels" : [
{'markup':"{dd}",'class':false,'id':false,'disabled':false},
{'markup':"{dd}"}
]
};
$.extend(settings, options);
return $(this).each(function() {
//the original dropdown element
var mainDropdown = $(this);
var defaultSelection = false;
var levels = {};
//insert dropdown into markup, and finally place it in the DOM, attaching events, etc.
var insertSelectDropdown = function(dd, level, sibling, position){
var markup = settings.levels[level] && settings.levels[level].markup ? settings.levels[level].markup : '{dd}';
//to support markup both placing the dropdown within a container and without a container,
//its necessary to use a little silly dom magic
var container = $('<div>'+settings.levels[level].markup.replace('{dd}',$('<div></div>').append(dd.addClass('ddlevel-'+level)).html())+'</div>').children()['insert'+position](sibling);
var select = container.parent().find('select.ddlevel-'+level).removeClass('ddlevel-'+level);
if (settings.levels[level]['class']){
select.addClass(settings.levels[level]['class']);
}
if (settings.levels[level].id){
select.attr('id',settings.levels[level].id);
}
if (settings.levels[level].disabled){
select.prop('disabled','disabled');
}
return select.data('level',level).data('container',container).data('levels',dd.data('levels')).change(updateDropdowns);
}
//produce markup for select element
var buildSelectDropdown = function(options, selected) {
var select = $('<select></select>').data('levels',options);
// Add options
$.each(options,function(index,value){
var option = $('<option></option>').html(index);
if (typeof(value) != 'object'){
option.val(value);
}
if (selected && index == selected){
option.attr('selected','selected');
}
select.append(option);
});
return select;
};
//the event function that runs each time a select input value changes
var updateDropdowns = function(){
var current = $(this).children(':selected').html();
var options = $(this).data('levels')[current];
//a non-object means this is the end of the line, set the value
if (typeof(options) != 'object'){
mainDropdown.val($(this).val());
}
else {
//remove any dds after the one that just changed
var dd = $(this);
while (dd.data('next')){
dd = dd.data('next');
dd.data('container').detach();
}
var level = $(this).data('level') + 1;
//add new dds
$(this).data('next',insertSelectDropdown(buildSelectDropdown(options, defaultSelection[level]), level, $(this).data('container').last(), 'After').change());
}
};
//build levels from initial dropdown
mainDropdown.children().each(function() {
var options = $(this).html().split(settings.delimiter);
if ($(this).is(":selected")){
defaultSelection = options;
}
var level = levels;
for (var i=0; i < options.length; i++) {
if (!level[options[i]]){
//either an option is an object pointing to other objects/values,
//or some other type value, indicating that the user has made a selection
level[options[i]] = ((i+1)==options.length) ? $(this).val() : {};
}
level = level[options[i]];
}
});
//if no default selection, use first value
if (!defaultSelection){
defaultSelection = mainDropdown.children().first().html().split(settings.delimiter);
}
insertSelectDropdown(buildSelectDropdown(levels,defaultSelection[0]), 0, mainDropdown, 'Before').change();
//hide initial dropdown
}).hide();
};
})(jQuery);
for (prop in array)
for (var i = 0; i < array.length; i++)
array.forEach()
for (item of array)
Object.defineProperty(Array.prototype, "associate", {
writable: false,
configurable: false,
enumerable: false,
value: function(keys) {
var result = {};
this.forEach(function (el, i) {
result[keys[i]] = el;
});
return result;
}
});