了解 JavaScript 闭包函数

Understanding JavaScript closure functions

本文关键字:函数 闭包 JavaScript 了解      更新时间:2023-10-17

我是Javascript的新手,对闭包函数有疑问。

在下面的代码中,我将创建一个闭包函数,并为同一函数设置一个新的属性名字。我想标识创建的函数的属性 - 名字 - 并使用代码 - console.log(obj1.firstname);来显示它。

但由于某种原因,它显示为未定义。请让我知道问题出在哪里。

<html>
  <head>
    <script>
      outerfunction = function(firstname,lastname) {
        var innerfunction = function (sex) {
        console.log(firstname);
        console.log(lastname);
        console.log(sex)
        }
        console.log('Initialize');
        innerfunction.prototype.firstname = firstname;
        return innerfunction;
      }
      obj1 = outerfunction('Bob','Mcdonald');
      console.log(obj1.firstname);
      obj2 = obj1('Male');
      obj1 = outerfunction('Lucy','Mary');
      obj1('Female');
    </script>
  </head>
  <body>
    This is the body
  </body>
</html>

问题在于您对原型的使用。如果您这样做innerfunction.firstname = firstname;那应该可以解决未定义的问题。

outerfunction = function(firstname,lastname) {
  var innerfunction = function (sex) {
    console.log(firstname);
    console.log(lastname);
    console.log(sex)
  }
  console.log('Initialize');
  innerfunction.firstname = firstname;
  return innerfunction;
}
obj1 = outerfunction('Bob','Mcdonald');
console.log(obj1.firstname);
obj2 = obj1('Male');
obj1 = outerfunction('Lucy','Mary');
obj1('Female');

只是评论:

>  outerfunction = function

应始终声明变量,尤其是全局变量,以便它们不会与具有相同名称或 ID 的 DOM 元素冲突(变量将优先(。一旦你声明了变量,那么在声明可以的地方分配一个函数表达式就没有意义了(如果没有别的,它不是键入的,但也使函数在执行任何代码之前可用,而不是在进行赋值时(。所以:

function outerfunction(firstname,lastname) { 

形式参数列表中的项(名字姓氏(有效地声明为局部变量。所以对于内部函数

  function innerfunction(sex) {
    console.log(firstname);
    console.log(lastname);
    console.log(sex)

此函数具有外部函数的名字和姓氏的闭包。

>         innerfunction.prototype.firstname = firstname;

仅当 innerfunction 是构造函数时才有用,并且仅当您希望实例继承 firstname 属性时,这才有用。函数不是从它们的公共原型继承,而是从它们的私有[[Prototype]]继承,这是它们构造函数在构造时的公共原型。

> obj1 = outerfunction('Bob','Mcdonald');

这将返回内部函数的"实例",该实例具有对名字姓氏的闭包。

> console.log(obj1.firstname);

但是名字属性obj1.prototype 上(因为那是分配它的地方(,所以找不到(检查obj1.prototype.firstname(。

您的部分困惑可能是作用域链上的标识符解析(即变量 firstnamelastname(与对象及其[[Prototype]]链上的对象属性解析(即继承和 innerfunction.protoype.firstname(之间的区别。