Javascript 试图完成这个闭包示例。。。?
我对此有些问题。我真的不明白我们如何得到字符串Javascript 试图完成这个闭包示例。。。?,javascript,function,closures,Javascript,Function,Closures,我对此有些问题。我真的不明白我们如何得到字符串“foobar”。我将写下我目前对这段代码的错误理解,希望有人能解释我错在哪里 o是具有属性foo的对象 foo对应于具有一个属性的对象,get。(这似乎是错的,但我看不出是怎么回事。) get对应于自调用匿名函数,该函数返回由一行组成的函数returnclosured+'bar' 也就是说,我希望o.foo返回一个对象,o.foo.get返回一个函数,o.foo.get()返回“foobar” 但事实并非如此,我也不知道为什么 另外,你为什么要这样
“foobar”
。我将写下我目前对这段代码的错误理解,希望有人能解释我错在哪里
o
是具有属性foo
的对象foo
对应于具有一个属性的对象,get
。(这似乎是错的,但我看不出是怎么回事。)get
对应于自调用匿名函数,该函数返回由一行组成的函数returnclosured+'bar'代码>
o.foo
返回一个对象,o.foo.get
返回一个函数,o.foo.get()
返回“foobar”
但事实并非如此,我也不知道为什么
另外,你为什么要这样写东西呢?为什么要写:
var o = Object.create({inherited: 1}, {
foo: {
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
}
});
o.foo; // "foobar"
而不是简单地:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
额外功能层有什么好处?两个问题的答案都可以在上找到。如果您阅读了有关属性的部分,您可以看到Object.create函数的第二个参数并不是简单地合并到原型中,而是一个包含getter、setter和各种选项的属性定义 考虑到这一点,请查看中的代码:
get: (function () { // a closure
var closured = 'foo';
return closured+'bar';
})()
正如您所说,为get分配了一个自调用匿名函数。此函数返回一个关闭closured变量并返回closured+bar值的函数。这并不等同于以下内容:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
原因是在这种情况下,为get分配了一个实际值而不是函数,这违反了Object.create所期望的属性规范。使用
get
可以为名为foo
的属性定义getter
方法。因此,每次您拥有对foo
的读取权限时,它都将执行getter方法。这就是为什么立即执行的函数本身返回一个函数(它是结果getter)
执行
o.foo
将导致对o
的foo
属性的读取访问,因此将执行getter。foo
对应于具有一个属性的对象,正如您所说,该属性是一个函数,但的第二个参数用于定义属性o.foo
是新对象o
的此类属性之一。它定义了一个getter,因此它不是一个“值属性”,而是一个“访问器属性”。尝试从o.foo
读取会导致调用getter
至于
get: (function () { // a closure
var closured = 'foo';
return closured+'bar';
})()
它返回一个函数,而
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
返回字符串'foobar'
,因此它们不等效,但第一个代码块等效于
get: (function () { // a closure
var closured = 'foo';
return closured+'bar';
})()
它也返回一个函数。在本例中,该闭包是无用的,但您可以这样做
get: function () { // a closure
var closured = 'foo';
return closured+'bar';
}
这样,getter和setter都可以访问closured
,但其他函数不能:
foo: (function() {
var closured = 'foo';
return {
'get': function () {
return closured+'bar';
},
'set': function (value) {
closured = value;
}
};
})()
关于代码,有几件事你没有正确理解
console.log(o.foo); // "foobar"
o.foo = "a";
console.log(o.foo); // "abar"
Object.create的第二个参数描述对象的属性。在本例中,get
部分实际上是一个getter,因此它描述了读取对象o
的foo
属性时发生的情况
这个结构被称为IIFE。它是一个立即被调用的函数。IIFE的优点是它创建了一个局部范围,因此closure
变量在外部范围中不可见。这避免了冲突
在第一种情况下,closured变量位于getter函数外部,而在第二种情况下,closured变量位于内部。处于外部意味着它的状态不会在每次调用函数(getter)时重置,并且它也可以在共享同一变量的其他函数中使用。下面是一个潜在的用例:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
// versus:
get: function () { // changed it a bit to be a getter
var closured = 'foo';
return closured+'bar';
}
闭包是访问函数外部变量的能力。我想你已经知道了
现在我们来谈谈为什么要这样做
var namespace = Object.create(null, {
uniqueId : {
get : (function(){
var counter = 0;
return function() {
return counter++;
};
})()
}
});
console.log(namespace.uniqueId); // 0
console.log(namespace.uniqueId); // 1
你们看,当你们这样做的时候,你们不仅可以得到“closured”变量,你们还可以修改它!(虽然您修改了它)现在“关闭”也不会被回收。因此,它将驻留在内存中,而不是在函数返回时清除。对象的第二个参数。create
应该是属性描述符对象。这是一个描述要添加到原型中的属性的对象,而不是对象本身。例如:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
var o = Object.create({inherited: 1}, {
foo: { /* ... property descriptor object ... */ },
bar: { /* ... property descriptor object ... */ }
});
在上面的示例中,我们向新对象的原型添加了两个属性:foo
和bar
。可以使用描述符对象以各种方式配置这些属性中的每一个
描述符对象接受几个配置属性,即:可配置
、可枚举
、值
、可写
、获取
、设置
在最初的示例中,您有效地为属性foo
配置了一个getter函数。如果希望简单地设置属性foo
的值,则必须在描述符内创建value
属性,并在其中添加所需的值(如果选择,它实际上是一个具有名为get
的属性的对象)。例如:
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
var o = Object.create({inherited: 1}, {
foo: { /* ... property descriptor object ... */ },
bar: { /* ... property descriptor object ... */ }
});
有关属性描述符对象的详细信息,请参阅:
var o = Object.create({inherited: 1}, {
foo: {
value: {get: (function () { /* ... code ... */ })() }
}
});