【问题标题】:Lexical environment rules seem to contradict non-primitive data types rules in Javascript词法环境规则似乎与 Javascript 中的非原始数据类型规则相矛盾
【发布时间】:2022-01-05 15:05:54
【问题描述】:

函数是一个对象,它是一种通过链接访问的非原始数据类型。当我们将函数分配给两个不同的变量时,预计当我们更改存储在函数内部的数据时,例如变量的值,在我们分配函数的变量之一中,它应该在两个变量中都更改为哪个函数被分配了。

但是,当为分配了相同函数的变量之一更改词法环境时,情况并非如此。在这种情况下,更改的数据仅针对存储在执行更改的变量中的函数的词法环境而更改。

目前,我无法从逻辑上解释这一点。下面的代码怎么可能一直为 messenger1 提供没有变化的结果?

const createMessenger = () => {
  let greeting = 'hi, buddy!';

  function sendMessage(name) {
    const sender = 'your master!';
    console.log(`${name}, ${greeting} It is ${sender}`);
  }

  function setGreeting(text) {
    greeting = text;
  }

  return {
    sendMessage,
    setGreeting,
  }
}

const messenger1 = createMessenger();
messenger1.sendMessage('Leonardo');

const messenger2 = createMessenger();
messenger2.sendMessage('Michelangelo');

messenger1.setGreeting('hiya!!!');
messenger1.sendMessage('Rafael');

messenger2.sendMessage('Donatello');
messenger1.sendMessage('Splinter');

控制台结果:

Leonardo, hi, buddy! It is your master!
Michelangelo, hi, buddy! It is your master!
Rafael, hiya!!! It is your master!
Donatello, hi, buddy! It is your master!
plinter, hiya!!! It is your master!

【问题讨论】:

  • 您遇到了什么问题?
  • How do I ask a good question?: "描述问题。“它不起作用”的描述不足以帮助人们理解您的问题。相反,告诉其他读者预期的行为应该是什么。告诉其他读者错误消息的确切措辞是什么,以及产生它的代码行。”
  • "当我们将一个函数分配给两个不同的变量时,预计当我们更改存储在函数内的数据时,例如变量的值,在我们要访问的变量之一中分配了函数,它应该在分配函数的两个变量中发生变化。“这是正确的。您根本没有分配 一个 对象,您有两个不同的对象。
  • "存储在函数内部的数据,例如变量的值" - 您可能会将作为函数关闭的词法环境一部分的变量与调用函数时创建。
  • 您是否意识到您的示例中有 5 个不同的函数对象?

标签: javascript object syntax


【解决方案1】:

您可以将变量绑定视为在初始化变量的行运行时创建。例如,无论何时

let greeting =

运行,创建一个新的greeting 标识符。

在您的代码中,每次调用 createMessenger 时,let greeting 行都会再次运行,从而为该调用创建一个新的 greeting。所以当你这样做时

const messenger1 = createMessenger();
const messenger2 = createMessenger();

您现在有两个单独的 greeting 绑定 - 一个在 messenger1 引用的闭包内,一个在 messenger2 引用的闭包内。

您在此处描述的行为:

当我们将函数分配给两个不同的变量时,预计当我们更改存储在函数内部的数据时,例如变量的值,在我们分配函数的变量之一中,它应该在函数已分配到的两个变量。

仅当 same 值分配给两个变量时才为真,在这种情况下,对一个内部的某些内容的更改确实在两个变量中都是可见的。如果您只调用了一次 createMessanger,并将结果对象分配给两个单独的变量,您会看到预期的行为。

const createMessenger = () => {
  let greeting = 'hi, buddy!';
  function sendMessage(name) {
    const sender = 'your master!';
    console.log(`${name}, ${greeting} It is ${sender}`);
  }
  function setGreeting(text) {
    greeting = text;
  }
  return {
    sendMessage,
    setGreeting,
  }

}

const messenger1 = createMessenger();
const messenger2 = messenger1;
messenger1.setGreeting('Greeting 1');
messenger2.sendMessage('Message 2');

上面,const messenger2 = messenger1; 表示两个 messanger 变量都持有对同一个对象的引用。

相比之下,做

const messenger1 = createMessenger();
const messenger2 = createMessenger();

创建两个完全不同的对象,因此对其中一个的更改不会影响另一个。

【讨论】:

  • 太棒了!我对作业的结果感到困惑。我错过了分配的对象不是我的函数,而是我的函数返回的对象,因此,完全不同的对象。请原谅我初学者的疑问。
猜你喜欢
  • 2014-10-12
  • 1970-01-01
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多