我的闭包示例不起作用

时间:2018-05-08 22:59:10

标签: javascript closures

我正在尝试找出闭包并创建了这个简单的示例,您可以使用名称调用函数greet,在第一次调用之后,greeting应该包含先前给定的名称。

所以,如果你打电话问候('安德鲁')并问候('约瑟夫')我希望在控制台上看到:

Hello Andrew
Hello Andrew, Joseph 

这是我的代码: https://codepen.io/anon/pen/pVpBdy

let greet = function(name) {
    let greeting = 'Hello ';

    let updateGreet = function() {
      greeting = greeting + ', ' + name; 
    }

    let printGreet = function() {
      console.log(greeting + name);
      updateGreet();
    }

    return printGreet();
} 

greet('Andrew');
greet('Joseph');

我看到的结果是:

Hello Andrew
Hello Joseph 

每当我打电话问候()时,问候语都会重新初始化,我不明白为什么。

请帮助我理解这一点。

4 个答案:

答案 0 :(得分:2)

您当前的greet可以调用创建一个自包含的对象 - 对象然后存储这些名称。每当您当前致电greet时,您都会创建一个单独的greeting变量,并将其封装在不同的对象中。

最简单的方法是立即执行该函数,以便对greet的所有调用都引用同一个对象。

您还应该将name变量传递给updateGreet



const greet = (() => {
  let greeting = 'Hello';
  const updateGreet = function(name) {
    greeting = greeting + ', ' + name;
  }
  const printGreet = function(name) {
    console.log(greeting + ', ' + name);
    updateGreet(name);
  }
  return printGreet;
})();

greet('Andrew');
greet('Joseph');
greet('Bob');




每当您声明一个不会改变其引用的变量时,请确保使用const - 这样可以让您更容易理解代码(无论是您还是其他人)。

答案 1 :(得分:0)

变量greeting绑定到函数greet的范围。因此,每次拨打greet()时,都会使用let greeting = 'Hello ';重新初始化问候变量

要获得所需的结果,您可以将let greeting = 'Hello '移到greet的范围之外,以便它保持不变。



let greeting = 'Hello ';
let greet = function(name) {
    let updateGreet = function() {
      greeting = greeting + ', ' + name; 
    }

    let printGreet = function() {
      console.log(greeting + name);
      updateGreet();
    }

    return printGreet();
} 

greet('Andrew');
greet('Joseph');




答案 2 :(得分:0)

我将假设您不太关心获取特定输出,但您关心理解这个概念。因此我简化了你的例子:

    $statement = $connection->prepare("
            INSERT INTO students (name_student,students,specialization,phone_num,paid,chair,group_id)
            VALUES (:name_student,:students,:specialization,:phone_num,:paid,:chair,:group_id)
        ");

        $result = $statement->execute(
            array(
                ':name_student' =>  $_POST["name_student"],
                ':students' =>  $_POST["students"],
                ':specialization'   =>  $_POST["specialization"],
                ':phone_num'    =>  $_POST["phone_num"],
                ':chair'    =>  "1",
                ':paid' =>  $_POST["paid"],
                ':group_id' =>  $_POST['group_id']


)
        );

这里发生的是当你第一次调用function greet (greeting) { return function person (name) { console.log(greeting + ',' + name) } } helloGreeting = greet('hello') helloGreeting('andrew') // 'hello, andrew' helloGreeting('joseph') // 'hello, joseph' 时,函数返回一个闭包 - greet。闭包是在另一个函数内声明的函数,并且由于在该函数内声明,它可以访问外部函数中定义的任何内容。

因此,在调用person之后,js返回greet('hello')函数,并且此函数可以访问先前定义的person变量。

特别是,函数person的执行上下文包含变量greeting。您可以将执行上下文视为一个框,并且每次通过调用greeting运行person时,此框还包含定义为hello的变量helloGreeting

这样的美妙之处在于,现在您还可以定义其他问候语。

greeting

这使得可以通过组合多个函数来构造真正可重用的代码。使代码模块化的一种非常好的方法!

答案 3 :(得分:0)

没有观察到闭包,因为greet函数不返回函数,而是函数调用,导致值undefined。要观察闭包,外部函数可以作为IIFE调用,并且应该返回存储在变量printGreet中的函数greet。现在greet引用了printGreet函数,它仍然保持与它的词汇环境的连接。

let greet = (function() {
  let greeting = 'Hello ';

  let updateGreet = function(name) {
    greeting = greeting + ', ' + name; 
  }

  let printGreet = function(name) {
    console.log(greeting + ', '+ name);
    updateGreet(name);
  }

  return printGreet;
}());

greet('Andrew');
greet('Joseph');