取消 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);

工作示例:https://jsfiddle.net/zjg2gbp3/3/

我一定是遗漏了什么但是...简单的连载就可以了:

您可以将一组元素传递给一个函数,该函数将添加您的位掩码。

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);
})