我真的不知道javascript关闭

时间:2015-01-18 21:22:59

标签: 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,结果是相同的)。如果function是primitive类型,我们应该不能为它附加属性。如果function是一个对象,我们可以使用引用传递来改变它的状态。

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

每个人都知道我们可以使用模块模式来使用对象来返回模块的API。 Mike Bostock展示here我们可以使用一个函数来实现与对象类似的东西,甚至更多,我们可以使用类似构造函数的东西。我以为我非常了解功能和对象。但有一些疯狂的想法,我很困惑。

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

1 个答案:

答案 0 :(得分:1)

我会猜测你会惊讶地发现以下内容 undefined

console.log(chart.__privateStatus.yscale);

这是因为执行以下行时:

render.__privateStatus = {
        yscale: yscale
    }

yscale 变量的值是 undefined ,因此这是分配的值。稍后更改变量的值无效。请注意,在javascript中,指定基元指定实际值,指定对象会指定对象的引用。因此,当__privateStatus传递对象的引用时, yscale 属性被赋予实际值 undefined

出于同样的原因:

console.log(chart.__privateStatus2.yscale);

返回undefined,因为有:

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());