【问题标题】:What's the difference between a boolean as primitive and a boolean as property of an object?作为原始对象的布尔值和作为对象属性的布尔值有什么区别?
【发布时间】:2017-06-22 02:01:36
【问题描述】:

我正在关注一些画布tutorial。下面的代码就是其中的一个sn-p。

在这个 sn-p 中,他们为什么不选择 runAnimation 是一个简单的布尔值?我认为x = !x 语句无论如何都会起作用,但是当我尝试将代码更改为使用布尔值时,代码不起作用。

那么,作为原始对象的布尔值和作为对象属性的布尔值有什么区别?

   /*
   * define the runAnimation boolean as an object
   * so that it can be modified by reference
   */
  var runAnimation = {
    value: false
  };

  // add click listener to canvas
  document.getElementById('myCanvas').addEventListener('click', function() {
    // flip flag
    runAnimation.value = !runAnimation.value;

【问题讨论】:

    标签: javascript html5-canvas


    【解决方案1】:

    所有参数在 JavaScript 中都是通过“值”传递的。这意味着当传递参数时,会传递存储在变量中的内容的副本。

    基元(如布尔值)存储它们所代表的实际数据,因此,当传递一个基元时,会发送数据的副本,从而生成两个副本数据。更改一个,不会影响另一个。

    但是,当您将对象分配给变量时,该变量存储了可以找到该对象的内存位置,而不是对象本身。将对象作为参数传递会导致传递内存地址的副本。在这些情况下,您可能会得到两个存储相同内存地址的变量,因此无论您使用哪个变量,都会影响同一个底层对象。

    在您的场景中,您当然可以仅使用一个布尔变量使其工作,但似乎本教程希望将其封装到一个对象中,这样布尔数据的副本就不会四处飘荡,并且会更少意外改变一个变量而不改变另一个变量的可能性。

    以下是一些基本示例:

    // This function takes a single argument, which it calls "input"
    // This argument will be scoped to the function.
    function foo(input){
      // The function is going to alter the parameter it received
      input = input + 77;
      console.log(input); 
    }
    
    var input = 100;  // Here's a higher scoped variable also called "input"
    
    foo(input);       // We'll pass the higher scoped variable to the function
    
    // Now, has the higher level scoped "input" been changed by the function?
    console.log(input);  // 100 <-- No, it hasn't because primitives pass a copy of their data
    
    // ************************************************
    
    // Now, we'll do roughly the same thing, but with objects, not primitives
    function foo2(obj){
      obj.someProp = 100;
      console.log(obj.someProp);
    }
    
    var obj = {
      someProp : 50
    };
    
    foo2(obj);
    
    // Here, we see that the original object has been changed by the funciton we passed it to
    console.log(obj.someProp);

    【讨论】:

    • 谢谢,我很高兴看到我的思路是正确的,但还没有完全到位。你的例子很清楚。就像在数学中一样,我们使用 () 来欺骗计算的顺序。在 JS 中我们可以使用对象来欺骗作用域/传值。
    • 您说过,“原语(如布尔值)存储它们所代表的实际数据,因此,当传递原语时,会发送数据的副本,从而产生两个数据副本。”字符串也是原语——这是否意味着传递一个字符串会导致一个字符串的两个副本?
    • @Mark 如果你传递一个字符串原语,是的。但是字符串也有一个对象类型,所以这取决于你处理的是字符串还是字符串。
    • @ScottMarcus 我说的是字符串原始类型。因此,如果我有一个包含 1000 万个字符的原始字符串并将其作为参数传递给函数,那么现在内存中会有两个具有数百万字节重复的字符串吗?这不是效率低下吗?
    • @Mark 正如我所说,“如果你传递一个字符串原语,是的”。在您的情况下,使用这样的字符串,您应该创建一个字符串对象(即let s = new String("string content here");),以便您只将对象引用的副本传递给内存中的对象,而不复制实际的字符串数据。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2013-04-26
    • 2010-11-20
    • 2023-04-10
    • 2011-01-29
    • 1970-01-01
    相关资源
    最近更新 更多