【问题标题】:node.js - why this local function can modify global variables?node.js - 为什么这个本地函数可以修改全局变量?
【发布时间】:2013-11-12 06:13:08
【问题描述】:

这是我的代码:

var handleCondition = function(condition,params){
  var dup_condition;
  dup_condition = condition;

  var isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  };

  var __replace = function(str){
    var reg_slot = /^#(.+)/;

    if(reg_slot.test(str) == true){
      var ss = reg_slot.exec(str)[1];
      return params[ss];
    }else{
      return str;
    }
  };

  var compare = function(a){
    var arr = a;
    if(params != undefined){
      for(var j =1;j<arr.length;j++){
        arr[j] = __replace(arr[j]);
      }
    }
    switch(arr[0]){
      case "$eq":
      case "==":
        return (arr[1] == arr[2]);
      default:
        return (arr[1] == arr[2]);
      }
    };

  if(isArray(dup_condition)){

    var im = function (arr){
      for(var i=0;i<3;i++){
        if(isArray(arr[i])){
          arr[i] = im(arr[i]);
      }
    }
    return compare(arr);
  };
  var res = im(dup_condition);
    return res;
  }
};

/*Here are test data*/
var c = {
  "beforeDNS":
  ["$eq","#host",["$eq",10,10]]
,
  "afterDNS":["$match",/^10\.+/,"#ip"]
};

var params ={
   host:"dd"
};

console.log(c["beforeDNS"]); // ==>  ["$eq","#host",["$eq",10,10]]
handleCondition(c["beforeDNS"],params);

console.log(c["beforeDNS"]);  // ==> ["$eq","dd",true]
handleCondition(c["beforeDNS"],params);

我第一次运行代码时的预期结果;
但是,当我第二次尝试运行该函数时,令我惊讶的是,c["beforeDNS"] 的值意外地发生了变化!
事实上,我并没有在我的函数中编写任何代码来修改这个全局变量的值,只是改变了。
所以请帮我找出这个神秘结果的原因或解决它。谢谢!

【问题讨论】:

    标签: node.js scope


    【解决方案1】:

    您的 dup_condition 变量没有重复任何内容。它只是对您传入的参数的引用。

    因此,当您将其传递给im 函数时,该函数会修改其参数,它只是引用和修改condition(它本身就是对在函数外部定义的c["beforeDNS"] 的引用)。

    要解决此问题,您可以使用slice 或更复杂的方法来实际欺骗参数。例如,slice 将返回一个新数组。请注意,这只是一个浅拷贝。该数组中的引用仍将引用相同的对象。

    例如:

    if (isArray(condition)) {
      var dup_condition = condition.slice();
      // ...
    }
    

    【讨论】:

    • 据我了解,var 的意思是初始化一个新变量,因此我认为这样就建立了一个新变量。那么你能解释一下var 在这个例子中的实际含义吗?是它像一个指针?
    • 建立了一个新变量,是的,但是该变量被分配了对对象的引用。它在某种意义上就像一个指针,但指的是对象本身,而不是内存地址。有很多关于这个的问题。这是一个起点:stackoverflow.com/questions/10231868/pointers-in-javascript
    【解决方案2】:

    在 javascript 中,对象是通过引用传递的。换句话说,在handleCondition dup_condition 中仍然指向同一个数组。所以,如果你在那里改变它,你实际上是在改变传递的对象。这是一个简短的例子,说明了同样的事情:

    var globalData = {
        arr: [10, 20]
    };
    
    var handleData = function(data) {
        var privateData = data;
        privateData.arr.shift();
        privateData.arr.push(30);
    }
    
    console.log(globalData.arr);
    handleData(globalData);
    console.log(globalData.arr);
    

    脚本的结果是:

    [10, 20]
    [20, 30]
    

    http://jsfiddle.net/3BK4b/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-08
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多