如何创建一个函数来创建一个不断返回对象键的函数

时间:2016-05-13 08:15:20

标签: javascript function

我试图创建一个函数来创建一个不断返回对象键的函数,但我不确定如何编写它。

例如,我可以执行以下操作:

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? 我不确定要搜索什么来找到解决方案。

感谢阅读:)

1 个答案:

答案 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>