javascript - 我真的不知道javascript闭包

标签 javascript closures

这是plunker .

function factory() {
    var yscale = function() {
        console.log("original");
    };
    var status = {
        yscale: yscale
    };

    function render() {
        yscale = function() {
            console.log("I am a scale");
        };
    }

    render.__privateStatus = {
        yscale: yscale
    };

    render.__privateStatus2 = status;

    render.__privateStatusGetter = function() {
        return status;
    };

    render.__privateStatusGetter2 = function() {
        return yscale;
    };

    return render;
}

var chart = factory();
chart();
console.log(chart.__privateStatus.yscale); // "original"
console.log(chart.__privateStatus2.yscale); // "original"

console.log(chart.__privateStatusGetter().yscale); // "original"
console.log(chart.__privateStatusGetter2()); // "I am a scale"

我在闭包中返回了一个函数,如果在闭包函数中发生了一些初始化,那么阻止新值显示为返回函数的状态的原因是什么?

有人可以帮忙从语言本身解释一下吗?

更新

根据@RobG的回答,我认为问题可以通过

简化
  • 函数是原始类型吗?
  • 函数和对象有什么区别?

你会注意到yscale是一个函数(在调用chart()之前它是未定义的,即使用函数初始化yscale,结果也是一样的)。如果函数是原始类型,我们不应该能够向它附加属性。如果函数是一个对象,我们可能可以使用引用传递来改变它的状态。

我知道我的第二个问题有点天真。如果您定义一个函数并让一个变量指向它,则不能通过将其分配给另一个函数来简单地更改其内部状态。但想想我的第一个问题——我们可以通过附加像 render.__privateMethods 这样的方法来改变函数(或函数指针)的状态来改变它的行为。

每个人都知道我们可以使用模块模式来使用对象来返回模块的 API。迈克·博斯托克 (Mike Bostock) 展示 here我们可以使用函数来实现类似的事情,就像对象一样,甚至更多,我们可以拥有类似构造函数的东西。我以为我对函数和对象都很了解。但有些胡思乱想,让我很困惑。

这就是我从 JavaScript 语言中寻找答案的原因,而不是从本能中寻找结果。

最佳答案

我猜测您会对以下返回未定义感到惊讶:

console.log(chart.__privateStatus.yscale);

这是因为当执行以下行时:

render.__privateStatus = {
        yscale: yscale
    }

yscale 变量的值未定义,因此这就是分配的值。稍后更改变量的值不会产生任何影响。请注意,在 javascript 中,分配原语会分配实际值,分配对象会分配对该对象的引用。因此,当 __privateStatus 传递对对象的引用时,yscale 属性会被分配实际值未定义

出于同样的原因:

console.log(chart.__privateStatus2.yscale);

返回未定义,因为存在:

var yscale;
var status = {
    yscale: yscale  // yscale is undefined when this assignment is made
};

所以 status.yscale 未定义,稍后:

render.__privateStatus2 = status;

被分配了对同一对象的引用。稍后更改yscale的值没有任何效果,其先前的值已被分配。

同样的情况:

console.log(chart.__privateStatusGetter().yscale); // undefined

要获取yscale的当前值,请将函数更改为:

render.__privateStatusGetter = function() {
    return yscale;  // use closure to variable to get current value
}

然后:

console.log(chart.__privateStatusGetter());

关于javascript - 我真的不知道javascript闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28014972/

相关文章:

javascript - 按照 jest docs 模拟 axios 但不工作

javascript - 为了建立价格查询服务或价格比较服务,我需要什么?

用于 twitter-bootstrap 的固定导航栏的 Javascript 在链接多个页面时不起作用?

javascript - Javascript 闭包总是保留作用域变量吗?

c++ - C++中的JavaScript样式关闭

swift - 使用闭包参数分配闭包

javascript - 云函数 - firestore : event. data.toJSON 不是函数

javascript - 替换 Cloudinary 上的图像

javascript - 奇怪的递归无限循环我无法追踪

javascript - javascript中自执行函数的目的是什么?