为什么这个 javascript 闭包没有像我希望的那样工作?

Why doesn't this javascript closure work as I hoped?

我写了这段代码,希望在 运行 document.ready() 部分之后 search_form.widget_date_range 对象上的 widget_controller 属性 成为一个控制器。令我惊讶的是,它是 undefined。这里出了什么问题?

search_form.widget_date_range = (function() {
  var element_selector = "div.date-range-slider";
  var settings = {
    bounds: {
      min: new Date(2003, 0, 1),
      max: new Date()
    },
    defaultValues: {
      min: new Date(2003, 0, 1),
      max: new Date()
    },
    wheelMode: "zoom",
  };
  var widget_controller = {};
  var onDocumentReady = function() {
    widget_controller = $(element_selector).dateRangeSlider(settings);
    widget_controller.on("valuesChanged", onDataChange);
    console.log(widget_controller);
  };
  var onDataChange = function(e, data) {
    // alert("Value just changed. min: " + data.values.min + " max: " + data.values.max);
    $("form#searching").trigger("submit");
  };
  return {
    onDocumentReady: onDocumentReady,
    widget_controller: widget_controller
  };
})();

$(document).ready(function() {
    ...
    search_form.widget_date_range.onDocumentReady();
});

我认为您在 JavaScript:

中遗漏了关于引用的一点
var search_form={};
search_form.widget_date_range = (function() {
   // Whatever code here

  // widget_controller variable references an empty object
  var widget_controller = {}; // #A
  var onDocumentReady = function() {
    // Here you redefine widget_controller,
    // but not the returned_object.widget_controller property
    widget_controller = $(element_selector).dateRangeSlider(settings); #B
    widget_controller.on("valuesChanged", onDataChange);
    console.log(widget_controller);
  };
  // Whatever here
  return {
    onDocumentReady: onDocumentReady,
    // returned_objet.widget_controller references the empty object
    widget_controller: widget_controller #C
  };
})();

一个解决方案可能是:

  ...
  return {
    onDocumentReady: onDocumentReady,
    get widget_controller() {
      return widget_controller; #D
    }
  };
  ...

JSFiddle 演示在这里:https://jsfiddle.net/xgya3mzh/2/

编辑:(似乎需要更多解释)

首先: { get property() {} } 语法来自 ES5,您可以在 MDN 上找到文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get

您可以使用另一种语法在 ES3 中完成相同的操作,在此处进行了解释:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineGetter(但仅当您希望支持 IE8 及更低版本时才使用此语法 - 我希望您不必这样做)。

#A 处声明变量 widget_controller 并将其设置为(几乎)空对象 ({}); (我说几乎是因为它仍然有一个带有一些继承方法和属性的原型)。

#C 处,您将对象字面量(将由闭包返回)的 属性 widget_controller 设置为空对象的引用。

#B,发生在 #C 之后,您重新定义闭包的 widget_controller,但您没有重新定义 widget_controller函数返回的对象,仍然引用空对象的值。

在我的代码中,在 #D 中,每当您访问闭包返回的对象的 属性 widget_controller 时,都会返回闭包的相同 widget_controller。

我希望它更清楚,虽然我不是很确定...