javascript - 试图理解这个函数定义的行为

标签 javascript module-pattern revealing-module-pattern

我不确定如何标题这个问题,但我正在使用带有构造函数的揭示模块模式,并注意到一些让我困惑的行为。这段代码的实际目的与我的问题无关,我只是想了解我看到的这种行为。

这是我遇到问题的代码:

var ajaxModule = (function() {
    //private
    var data,callBack,type,dataType,url,
    //public
    constructor;

    constructor = function(callBack,data,type,dataType,url) {
        //Required
        callBack = callBack || null;
        data = data || null;
        //Defaults
        type = type || 'POST';
        dataType = dataType || 'json';
        url = url || 'DBConnect.php';
    };

    //methods
    function setAjaxQuery() {
        log('in setAjaxQuery')
        dir(callBack);
        dir(data);
        dir(type);
        dir(dataType);
        dir(url);
    };

    constructor.prototype = {
        constructor: ajaxModule,
        setAjaxQuery: setAjaxQuery,
    };

    return constructor;
}());

现在调用它:

var ajax = new ajaxModule('someObject','someData');
ajax.setAjaxQuery();

现在这样做,我发现 setAjaxQuery 函数中所有 console.dir() 命令都未定义。

我发现问题是参数名称与局部变量相同。我通过执行以下操作解决了该问题:

constructor = function(zcallBack,zdata,ztype,zdataType,zurl) {
    //Required
    callBack = zcallBack || null;
    data = zdata || null;
    //Defaults
    type = ztype || 'POST';
    dataType = zdataType || 'json';
    url = zurl || 'DBConnect.php';
}

我的问题是为什么会发生这种情况?当名称相同时,javascript 做了什么会导致此问题?

最佳答案

当您添加参数时,它们会为您提供的名称保留本地范围。由于外部作用域具有您尝试访问的这些名称的版本,因此您无法重用这些名称,否则冲突将导致仅使用本地作用域。由于第二个调用函数只能访问外部作用域,因此无法检索内部作用域中设置的值。

词法作用域可能会变得很奇怪,但让我们考虑一个例子:

function x(){
  var a = 5; // scoped to x
  var b = 10; // scoped to x
  function c() {
    var a = 10; // scoped to c, this is equivalent to having an argument named a
    return a + b; // b is scoped to x
  }
  return c; // scoped to x
}

我对这些情况的建议是使用参数化来解决问题:

var ajaxModule = (function() {
    //private
    var inner = {
      data: null,
      callBack: null,
      type: 'POST',
      dataType: 'json',
      url: 'DBConnect.php'
    },
    //public
    constructor;

    constructor = function(callBack,data,type,dataType,url) {
        //Required
        inner.callBack = callBack || null;
        inner.data = data || null;
        //Defaults
        inner.type = type || 'POST';
        inner.dataType = dataType || 'json';
        inner.url = url || 'DBConnect.php';
    };

    //methods
    function setAjaxQuery() {
        log('in setAjaxQuery')
        dir(inner.callBack);
        dir(inner.data);
        dir(inner.type);
        dir(inner.dataType);
        dir(inner.url);
    };

    constructor.prototype = {
        constructor: ajaxModule,
        setAjaxQuery: setAjaxQuery,
    };

    return constructor;
}());

这样,您就可以同时保持命名约定并通过(内部)显式声明您的范围。

关于javascript - 试图理解这个函数定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24312321/

相关文章:

javascript - 您可以将多个文件缩小为一个文件吗?

javascript - 揭示模块模式内部外部变量不匹配

javascript - CanvasJS .render() 函数跳转到屏幕顶部

javascript - 非常简单的 JavaScript 问题

php - 从已知位置查找最近的列出(数组?)城市

javascript - 动态更改验证码语言

javascript - Javascript Module Pattern 可以用于单例,也可以用于实例化多次的对象吗?

design-patterns - 显示模块模式的轻微变化

javascript - 保护对象文字并防止它们被覆盖的良好实践