我试图创建一个函数来创建一个不断返回对象键的函数,但我不确定如何编写它。
例如,我可以执行以下操作:
var parent = {data: 123}
var child = {}
child.data = function() {
return parent.data
}
child.data() // 123
parent = {data: 456}
child.data() // 456
这很好用,但我想创建一个创建数据函数的函数,如:
var parent = {data: 123}
var child = {}
create_data_function(parent, child, "data")
child.data() // 123
parent = {data: 456}
child.data() // 456
以下内容不起作用,因为"来自"变量被重新分配
function create_data_function(from, to, key) {
to[key] = function() {
return from[key]
}
}
是否可以创建create_data_function? 我不确定要搜索什么来找到解决方案。
感谢阅读:)
答案 0 :(得分:0)
让我们引用parent
指向对象1的初始对象,以及指定给parent
作为对象2的新对象。
parent
变量中的值是一个对象引用,最初是对象1的引用。当你这样做时:
create_data_function(parent, child, "data");
parent
的值被读取并传递到create_data_function
。该值是对象1的引用。与parent
变量相关的任何内容都不会传递到create_data_function
。它创建的函数将关闭创建它的from
调用的create_data_function
参数,该调用将始终包含对Object 1的引用。
要创建一个执行所描述内容的函数,该函数必须能够访问parent
变量本身。 JavaScript没有任何形式的pass-by-reference(允许您将对变量的引用传递给函数),因此我们必须找到另一种方法来create_data_function
访问parent
变量
最简单的方法是确保create_data_function
关闭 parent
,方法是在可以访问parent
的范围内定义它,如下所示:< / p>
var parent = {data: 123};
var child = {};
create_data_function(child, "data");
// ^---- Note we aren't passing in `parent`
snippet.log(child.data()); // 123
parent = {data: 456};
snippet.log(child.data()); // 456
function create_data_function(to, key) {
// Note no `from` ------------^
to[key] = function() {
return parent[key];
// ^^^^^^------ instead we use `parent` directly
};
};
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
这是可能的,因为create_data_function
是在您可以直接使用parent
变量的地方创建的。
但是如果没有呢?我们通过将访问者函数传递给create_data_function
来解决它,如下所示:
// Note that because `parent` is a local within `test`,
// and `create_data_function` isn't, `create_data_function`
// doesn't have direct access to `parent` (it doesn't *close over*
// `parent`).
function test() {
var parent = {data: 123};
var child = {};
create_data_function(function() { // So we give it a function to call
return parent; // to get `parent`'s current value
}, child, "data");
snippet.log(child.data()); // 123
parent = {data: 456};
snippet.log(child.data()); // 456
}
function create_data_function(fromAccessor, to, key) {
// Accept the accessor -------^
to[key] = function() {
return fromAccessor()[key];
// Call it ----^^^^^^^^^^^^^^
};
};
test();
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
由于新的箭头功能,ES2015的语法不那么笨重了:
// THIS EXAMPLE REQUIRES ES2015 SUPPORT IN YOUR BROWSER
function test() {
var parent = {data: 123};
var child = {};
create_data_function(() => parent, child, "data");
// The accessor func ^^^^^^^^^^^^
snippet.log(child.data()); // 123
parent = {data: 456};
snippet.log(child.data()); // 456
}
function create_data_function(fromAccessor, to, key) {
to[key] = function() {
return fromAccessor()[key];
};
};
test();
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>