0

在 javascript 代码中,我有一个字符串,它定义了对象内的属性路径。例如

var def = "contact.email"

如何从此字符串中获取以下函数?

o => o.contact.email

这样我就可以通过以下方式使用它:

var person = {
    name: 'Test',
    contact: { email: 'test@test.test' }
}

var emailGetter = MagicCompileFunction('contact.email');

var email = emailGetter(person);
// here, email should hold the value of person.contact.email

路径字符串在编译时是未知的。它也可以由用户提供。

该解决方案也应该在非浏览器环境中工作(没有window对象),例如在 NodeJS 服务器端 javascript 中。

我知道一种解决方案是创建一个通用方法,它将一个对象和一个字符串作为参数(valueGetter(person, "contact.email")例如),其中字符串定义对象内的路径,然后在每个点上拆分字符串'。并按照对象上的路径。但我不希望这个算法在每次调用getter函数时都执行。我需要一个动态编译的方法,它会给我一个最终的 getter,它可以立即访问所需的(子)属性。

4

4 回答 4

3

ES6 比Archer 的回答稍微多一点:

function MagicCompileFunction(mapping) {
	return (obj => mapping.split(".").reduce((curr, name) => curr[name], obj));
}

var person = {
    name: "Test",
    contact: {
		email: "test@test.test"
	}
}

var emailGetter = MagicCompileFunction("contact.email");
var email = emailGetter(person);

var nameGetter = MagicCompileFunction("name");
var name = nameGetter(person);

console.log(email);
console.log(name);

于 2017-04-12T13:33:08.563 回答
2

您可以使用Function 构造函数来实现这一点

var person = {
    name: 'Test',
    contact: { email: 'test@test.test' }
}
var maginFunction = (def) => new Function('o','return o.'+ def);

var emailGetter = maginFunction('contact.email');

var email = emailGetter(person);
console.log(email);
于 2017-04-12T13:25:50.133 回答
1

我喜欢这个问题,所以我想出了一个解决方案。这应该可以满足您的要求,而无需使用 eval ...

function MagicCompileFunction(mapping) {
	mapping = mapping.split(".");
	return (function(obj) {
		var result = obj;
		for (var idx in mapping) {
			result = result[mapping[idx]];
		}
		return result;
	});
}

var person = {
    name: "Test",
    contact: {
		email: "test@test.test"
	}
}

var emailGetter = MagicCompileFunction("contact.email");
var email = emailGetter(person);

var nameGetter = MagicCompileFunction("name");
var name = nameGetter(person);

console.log(email);
console.log(name);

返回一个函数,该MagicCompileFunction()函数使用您在创建 getter 对象时使用的映射进行初始化。然后您可以将任何人传递给该对象以返回相关数据。

于 2017-04-12T13:25:43.663 回答
0

您可以简单地如下动态访问嵌套对象属性;

function dynPropAcc(o,s){
  return s.split(".")
          .reduce((p,q,i) => i-1 ? p[q] : o[p][q]);
}

var def = "contact.email.2",
    obj = {contact: {name: "John", email: { 1: "john@x.com", 2: "john@y.com"}}};

console.log(dynPropAcc(obj,def));

于 2017-04-12T13:29:44.743 回答