取消 javascript 中的位产生错误的值
unsetting bits in javascript producing wrong value
我有 4 个复选框。如果按下所有 4 个复选框,我想生成 Number
15,例如“0000 1111”。如果 none 个复选框被点击,那么它应该产生 0,例如“0000 0000”。换句话说,当复选框被点击时,相关位应该被设置,否则它应该被取消设置。每个复选框都以 2 的次方提升,以定位下一位:
<input type="checkbox" name="validation_rules" id="inlineCheckbox1" value="1">
<input type="checkbox" name="validation_rules" id="inlineCheckbox2" value="2">
<input type="checkbox" name="validation_rules" id="inlineCheckbox4" value="4">
<input type="checkbox" name="validation_rules" id="inlineCheckbox8" value="8">
我可以正常设置这些位:
相关方法如下:
listen_for_enabled_change: function(){
$form.on('click', 'input[name="validation_rules"]', function(){
var $hidden = $(this).closest('.field-border').find("input[type='hidden'][name='result']");
var new_val;
if($(this).get(0).checked) {
new_val = $hidden.val() | $(this).val();
} else {
var mask = 1 << $(this).val()/2;
new_val = $hidden.val() & ~mask;
}
$hidden.val(new_val);
})
}
不幸的是,取消设置位在上面的代码中不起作用。例如,如果隐藏的输入字段值为 8。然后我取消选中值为 8 的复选框,它应该生成 0。但是,它根本不会更改值。它只是 returns Number
8. 我可能做错了什么?
我认为你的问题出在这里:
var mask = 1 << $(this).val()/2;
new_val = $hidden.val() & ~mask;
值为 [1,2,4,8]
,这将导致整数 [0,1,2,4]
。是的,那是 4
,应该是 3
。
为什么不将复选框值标记为需要设置的位索引呢?
<input type="checkbox" name="validation_rules" id="inlineCheckbox1" value="0">
<input type="checkbox" name="validation_rules" id="inlineCheckbox2" value="1">
<input type="checkbox" name="validation_rules" id="inlineCheckbox4" value="2">
<input type="checkbox" name="validation_rules" id="inlineCheckbox8" value="3">
那么你可以:
if($(this).get(0).checked) {
// flip on the bit at the bit index
new_val = $hidden.val() | (1 << $(this).val());
} else {
// flip off the bit at the bit index
new_val = $hidden.val() & ~(1 << $(this).val());
}
或者整个事情,稍微清理一下:
var $this = $(this);
var $hidden = $("#result");
var newVal = $hidden.val();
var bit = $this.val()
if (this.checked) {
newVal = newVal | (1 << bit);
} else {
newVal = newVal & ~(1 << bit);
}
$hidden.val(newVal);
我一定是遗漏了什么但是...简单的连载就可以了:
您可以将一组元素传递给一个函数,该函数将添加您的位掩码。
var getBitmask = function(els){
return Array.prototype.reduce.call(Array.prototype.filter.call(els, function(el){
return el.checked;
}), function(a, b){
return {value: ~~a.value + ~~b.value};
}).value;
};
console.log(getBitmask(document.querySelectorAll('input[type=checkbox]')));
以上在没有 jQuery 的情况下也有效。
您也可以围绕元素索引自动构建位掩码。
在我看来,基于刚刚选中的复选框的所有位屏蔽和移位都不必要地复杂(过早优化?),而不是根据复选框操纵当前 $hidden
值刚刚检查过,您只需在每次 any 复选框更改时简单地合计值,您就会获得更具可读性/更不容易出错的代码:
$form.on('change', 'input[name="validation_rules"]', function () { // 'change' is more robust than 'click' here
var new_val = 0;
$('input[name="validation_rules"]').each(function(i, elem) {
if (elem.checked) {
new_val += parseInt(elem.value, 10);
}
});
$hidden.val(new_val);
})
我有 4 个复选框。如果按下所有 4 个复选框,我想生成 Number
15,例如“0000 1111”。如果 none 个复选框被点击,那么它应该产生 0,例如“0000 0000”。换句话说,当复选框被点击时,相关位应该被设置,否则它应该被取消设置。每个复选框都以 2 的次方提升,以定位下一位:
<input type="checkbox" name="validation_rules" id="inlineCheckbox1" value="1">
<input type="checkbox" name="validation_rules" id="inlineCheckbox2" value="2">
<input type="checkbox" name="validation_rules" id="inlineCheckbox4" value="4">
<input type="checkbox" name="validation_rules" id="inlineCheckbox8" value="8">
我可以正常设置这些位:
相关方法如下:
listen_for_enabled_change: function(){
$form.on('click', 'input[name="validation_rules"]', function(){
var $hidden = $(this).closest('.field-border').find("input[type='hidden'][name='result']");
var new_val;
if($(this).get(0).checked) {
new_val = $hidden.val() | $(this).val();
} else {
var mask = 1 << $(this).val()/2;
new_val = $hidden.val() & ~mask;
}
$hidden.val(new_val);
})
}
不幸的是,取消设置位在上面的代码中不起作用。例如,如果隐藏的输入字段值为 8。然后我取消选中值为 8 的复选框,它应该生成 0。但是,它根本不会更改值。它只是 returns Number
8. 我可能做错了什么?
我认为你的问题出在这里:
var mask = 1 << $(this).val()/2;
new_val = $hidden.val() & ~mask;
值为 [1,2,4,8]
,这将导致整数 [0,1,2,4]
。是的,那是 4
,应该是 3
。
为什么不将复选框值标记为需要设置的位索引呢?
<input type="checkbox" name="validation_rules" id="inlineCheckbox1" value="0">
<input type="checkbox" name="validation_rules" id="inlineCheckbox2" value="1">
<input type="checkbox" name="validation_rules" id="inlineCheckbox4" value="2">
<input type="checkbox" name="validation_rules" id="inlineCheckbox8" value="3">
那么你可以:
if($(this).get(0).checked) {
// flip on the bit at the bit index
new_val = $hidden.val() | (1 << $(this).val());
} else {
// flip off the bit at the bit index
new_val = $hidden.val() & ~(1 << $(this).val());
}
或者整个事情,稍微清理一下:
var $this = $(this);
var $hidden = $("#result");
var newVal = $hidden.val();
var bit = $this.val()
if (this.checked) {
newVal = newVal | (1 << bit);
} else {
newVal = newVal & ~(1 << bit);
}
$hidden.val(newVal);
我一定是遗漏了什么但是...简单的连载就可以了:
您可以将一组元素传递给一个函数,该函数将添加您的位掩码。
var getBitmask = function(els){
return Array.prototype.reduce.call(Array.prototype.filter.call(els, function(el){
return el.checked;
}), function(a, b){
return {value: ~~a.value + ~~b.value};
}).value;
};
console.log(getBitmask(document.querySelectorAll('input[type=checkbox]')));
以上在没有 jQuery 的情况下也有效。
您也可以围绕元素索引自动构建位掩码。
在我看来,基于刚刚选中的复选框的所有位屏蔽和移位都不必要地复杂(过早优化?),而不是根据复选框操纵当前 $hidden
值刚刚检查过,您只需在每次 any 复选框更改时简单地合计值,您就会获得更具可读性/更不容易出错的代码:
$form.on('change', 'input[name="validation_rules"]', function () { // 'change' is more robust than 'click' here
var new_val = 0;
$('input[name="validation_rules"]').each(function(i, elem) {
if (elem.checked) {
new_val += parseInt(elem.value, 10);
}
});
$hidden.val(new_val);
})