通过此关键字声明变量是否存在任何缺陷?

时间:2017-05-17 13:49:01

标签: javascript node.js ecmascript-6

我写了一个简单的对象解构函数,它通过为范围对象赋值属性来声明给定范围内的变量

我可以在生产中使用此功能,如果不是,使用这样的功能会有什么缺陷吗?



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




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);