繁体   English   中英

如何在JavaScript中“从对象中取出变量”

[英]How to “take variables out of an object” in javascript

我正在寻找将对象内容导入全局范围的方法:

var y = {}
y.x = 5

//do some magic here

console.log(x); //5

我想这样做是为了使我可以使用易于记忆的函数名称来创建一个易于使用的模块,而不必担心其他模块意外覆盖的情况。

考虑以下示例:

funModule = {};

funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc

funModule.UNITED_STATES_DEFICIT = ...;

在这里,我创建了一个模块,其中包含一些有用的函数和常量(实现和值已替换为“ ...”)。

我不希望我的用户每次调用函数或使用常量时都必须键入模块名称。 这将导致真正混乱的代码:

funModule.walkDog(funModule.UNITED_STATES_DEFICIT);

我可以通过全局定义所有内容来再次尝试:

washClothes = function(clothes){...}
walkDog = function(dogName){...}
//etc

UNITED_STATES_DEFICIT = ...;

但是如果另一个模块也定义了通用命名的washClothes函数,我们就会遇到麻烦。 (在我的实际情况下, run通用函数)


从技术环境中删除,这是我面临的问题:

首先,我想使用简单易记的名称来使该模块易于学习和使用。

其次,我不希望这些简单的名称使该模块无法与他人一起使用。 特别是随着它的增长,将使用许多通用名称。 如果用户可以决定是否直接导入名称,那就太好了。

第三,当我输入此内容时,我意识到我所描述的内容已经在python中已经存在。 有关更多详细信息,请参见http://effbot.org/zone/import-confusion.htm

tl; dr如何使用javascript完成类似python的导入?

编辑:

似乎没有通用的方法可以做到这一点。

  • 使用Window并非在所有环境中都可以使用(但可以在任何常见的浏览器中使用)。
  • 显然,ES6模块不能直接用于Web浏览器。

这个问题是从不同的这一个 ,因为它不是关于Node.js的 我一直在寻找一种通用的方法来做,但这似乎是不可能的,所以我将其限制在Web浏览器中(即chrome,firefox,safari,opera,也许也就是)

编辑:

这篇关于范围的一般文章对任何与我有类似问题的人都可能有用: https : //toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/

ES6模块就是您想要的。 如果将对象定义为es6模块,则可以执行此操作(使用示例中的名称):

import { washClothes } from "fun-module";

然后, washClothes将在导入它的文件上全局可用,就像您想要的那样。

在这里阅读

如果您真的想要一个神奇的解决方案,例如您的帖子中的评论,并且不想使用ES6并且在浏览器中运行,则可以将其放在window对象上:

window.x = 5

在JavaScript中,至少在浏览器中,全局变量是window对象的属性:即window.xx (其中x为全局)引用相同的值。 因此,从理论上讲,您可以使用Object.assign()将对象的属性复制到使它们成为全局变量的window对象。 这大致等效于Python中的globals().update(myobj.__dict__)

但是就像import *在Python中通常是个坏主意一样,这听起来也像个坏主意,除了更糟的是,因为window还有很多其他属性,您可能不想破坏它。

 Object.prototype.makeglobal=function(){   
    for(key in this){
      if(window[key]){//replace window if youre not in a browser
      //already exist, error handling
      console.error(key+' already exist in window');
   }else{
      window[key]=this[key];
   }}};

像这样使用:

funModule.makeglobal();
//now you can
washClothes();

但这很不好,因为它污染了全局对象。

2.您的用户应创建自己的名称空间:

function(){
 this.washClothes();
//more of his content
}.call(funModule);

3,您还可以添加一个加载器:

funModule.load=function(func){
    console.log(func); 
    console.log(this);
    func.call(this,this);
};

现在您可以执行以下操作:

funModule.load(function(fun){
 this.washClothes();
 fun.washClothes();
 });

4.如果您担心可读性,可以使用函数链接(?):

funModule.washClothes=function(){
  //your code
   return this;
 } 

现在您可以执行以下操作:

funModule.washClothes("tshirts").washClothes("trousers").washClothes();

经过一些额外的研究,我找到了一种在不污染全局名称空间的情况下允许用户直接访问模块内容的方法。

该解决方案允许用户:

  1. 编写直接引用模块功能/属性的代码
  2. 如果有多个以相同样式编写的模块,请定义优先级
  3. 仍按模块名称访问模块的功能/属性*

*此功能附带一个陷阱

这是代码


模组

funModule = {};

//This stuff is the arbitrary contents of the module:

funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc

funModule.UNITED_STATES_DEFICIT = ...;
//etc

//This part is necessary:

funModule.run(userApp)
{

  for(key in this){
    eval(key + " = " + this[key] + ";");
  }

  userApp();

}

在funModule.run的作用域和funModule中动态定义函数的唯一方法(我可以找到)是使用Eval。 使用调用,应用或绑定来操纵范围仍然需要使用this关键字,这种不寻常样式的全部要点是使客户端代码尽可能简单且不重复。

客户代码1

function myApp()
{
    washClothes(UNITED_STATES_DEFICIT);
}
funModule.run(myApp);

在客户端代码中,可以直接访问除funModule.run之外的funModule.run 因此,全局名称空间保持干净,但用户的代码不需要不必要的重复。

客户代码2

function myApp()
{
    washClothes(UNITED_STATES_DEFICIT);
}
funModule.run( otherModule.run.bind({},myApp) );  //otherModule has precedence here

假设otherModule是具有相同run功能的其他模块。 funModule将加载其内容,然后调用其第一个参数。 第一个参数将加载otherModule的内容,覆盖从任何funModule具有相同的名称。

客户代码3

function myApp()
{
    //directly access stuff from funModule
    walkDog()
    var big = UNITED_STATES_DEFICIT * 3.14;

    //explicitly access stuff from specific modules
    clothes = new otherModule.Clothes();
    funModule.washClothes(otherModule.washClothes(clothes));
}
funModule.run(myApp)

这是需要使用eval的功能。 用户可以选择避免直接访问的歧义。 他们仍然可以通过命名它们来自的模块来访问属性/方法。

但为什么?

可以理解的是,一些StackOverflow用户担心问题中的异常约束,因此我认为我会回答以下问题:

为什么不为模块使用简短的别名。

我试图在本文中回答这个问题, 该文章来自这个问题与解答。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM