我写了一个简单的对象解构函数,它通过为范围对象赋值属性来声明给定范围内的变量
我可以在生产中使用此功能,如果不是,使用这样的功能会有什么缺陷吗?
function destructure(obj, scope) {
scope = scope || this;
Object.keys(obj).forEach(key => {
if (scope[key] === undefined) {
scope[key] = obj[key];
} else {
throw new Error(key + ' variable is already declared.');
}
});
}
var o = {
one: 1,
two: 2,
three: 3,
four: 4
};
destructure(o);
console.log(one); // 1
console.log(two); // 2
console.log(three); // 3
console.log(four); // 4

答案 0 :(得分:3)
通过
this
关键字声明变量是否存在任何缺陷?
是的:它确实不起作用。
可能存在对this
和范围如何工作的误解。
关于范围
只有当环境由实际对象支持时,才能通过向对象添加属性来声明变量。这只是两种情况的情况:
window
)(部分)支持with
声明示例:
// Global scope
window.foo = 42;
console.log(foo);
// with statement
var obj = {};
with (obj) {
obj.bar = 21;
console.log(bar);
}
既然你提到你正在使用Node,我想强调 function 范围和模块(它们只是Node中的函数)at范围不由对象支持,因此无法动态声明变量。
关于this
this
的值取决于函数的调用方式。它基本上可以引用任何值。
现在,调用(n unbound)函数的“正常方式”,即f()
,具有this
将引用全局对象的任意行为,例如浏览器中的window
。当然,作为全球范围,任何其他变量都可以在其他地方访问,但这不一定是好事。
因此,虽然您的解决方案可能似乎正常工作,但只有在全局范围内运行代码时,它才会巧合。
关于严格模式
Strict mode更改了一些被视为不正确或危险的行为。最重要的是,它会改变正常函数调用(this
)内部f()
的行为方式。它不是引用全局对象,而只是undefined
。因此,如果您的函数是在严格模式下声明的,那么您的代码实际上会抛出错误。
with
语句在严格模式下也是禁止的。
使用ES2016,默认情况下,类和模块等新结构是严格的,因此您可以看到这是语言开发的方向,您不应该依赖于在严格模式下不起作用的行为。
答案 1 :(得分:1)
这是以下的程序化方法:
this["one"] = 1
this["two"] = 2
this["three"] = 3
this["four"] = 4
虽然这在理论上很好,但依靠this
可能会遇到麻烦。最好直接指定global
,这样您就不会遇到.bind()
和朋友的麻烦。
function destructure(obj, scope) {
scope = scope; // Remove the this
Object.assign(scope, obj);
}
destructure(o, global) // Explicitly declare global scope
至于内存泄漏,性能等(我觉得这个问题更多),你必须记住,你分配给global
的所有内容都不会收到垃圾。你应该只添加global
的功能,只有你真的必须这样做。
答案 2 :(得分:1)
通过为范围对象
分配属性来声明给定范围内的变量
不,这不是变量声明的工作原理。此外,JS可用的唯一“范围对象” - 忽略with
语句 - 是全局对象(您在概念证明中碰巧使用它),并且您不希望弄乱了。
我可以在制作中使用此功能吗?
绝对不是。
如果你的想法被卖掉了,你可能会can hack it with eval
,但实际上你只是should use real destructuring like everyone else:
var {one, two, three, four} = o;
答案 3 :(得分:0)
为什么不使用Object.assign?
StateClient sc = activity.GetStateClient();
BotData userData = sc.BotState.GetUserData(activity.ChannelId, activity.From.Id);
UserDetails usr = new UserDetails();
usr.EmailId = "test@gmail.com";
userData.SetProperty<string>("EmailId", usr.EmailId);
sc.BotState.SetUserData(activity.ChannelId, activity.From.Id, userData);