【问题标题】:Javascript, Push Property Into parent's scopeJavascript,将属性推送到父级范围
【发布时间】:2014-08-15 00:35:59
【问题描述】:

我正在构建一些 node.js 模块,并且我想将一些库推送到这个对象中

在这个场景中,我有

app.js

var api = require('./scripts/api.js');
var oauth = require('./scripts/oauth.js');
var db = require('./scripts/db.js')
var libraries  = {
    api : api,
    db : db,
    oauth : oauth,
}

var modules = require('./scripts/module.js');
modules.init(app, libraries);

模块.js

module.exports = { 

    init : function(app,libraries) {
        for (key in libraries) {
            if (libraries.hasOwnProperty(key)) {
                this[key] = libraries[key]
            }
        }

        this.oauth.init(app,libraries);
    }
}

api.js

module.exports = { 

init : function(app, libraries) {
    for (key in libraries) {
        if (libraries.hasOwnProperty(key)) {
            this[key] = libraries[key]
        }
    }
    app.get('/api/linkedin/posts', function (req, res) {

        //get the credentials
        var userid = req.session.user_id;
        var credentials = '';
        getCredentials('linkedin',userid)
            .then(function(result) {
                this.db.store(credentials = JSON.parse(result))
                    })
    });
}, 
}

它工作正常,但是我希望发生的不是将它推到模块对象本身上。将其推送到对象范围,这样我就不必将 this.library.function() 添加到所有内容中。这样我就可以直接调用 oauth.init() 访问库了,有什么好的方法吗?

我想要完成的是产生与我执行以下操作相同的效果,我只是想让这些引导方法变得神奇

模块.js

var api = {}
var oauth = {}

module.exports = { 

    init : function(app,libraries) {
        api = libraries.api
        oauth = libraries.oauth

        oauth.init(app,libraries);
    }
}

这是一个演示问题的小提琴http://jsbin.com/cadejukijudu/1/edit

【问题讨论】:

  • 你能展示一下你是如何调用的吗?
  • @cgatian,我想要一种将变量从 init 中绑定到对象范围内的方法,就像我在模块上方完成了 var oauth = {} 和 var api = {} 一样。导出,然后从 init 中分配值。我已经更新了问题
  • 那么你是想避免api.init()、oauth.init()吗?
  • @cgatian 不,我很好,我想避免放置它。在每次调用 this.oauth this.api 之类的库之前,我只想调用 oauth.init() api.init() 而不是 this.oauth.init()
  • 对象没有作用域,只有函数有,而且你不能以编程方式访问它们。相关:Add variable to a functions scopeJS class without constant reference to “this” for member access

标签: javascript node.js


【解决方案1】:

@Matthew Bucci:你的问题让我很困惑——不是因为你的编码风格,而是因为问题的描述和程序设计——所以我开始稍微重写你的问题并添加 cmets .希望问题及其答案将变得显而易见;如果不是我,那就是别人。


您的问题:

App.js

var libraries = {
    "api": require('./scripts/api.js'),
    "db": require('./scripts/db.js'),
    "oauth": require('./scripts/oauth.js')
};

var modules = require('./scripts/module.js');
modules.init(app, libraries);
// Where does the app variable come from?
// The naming of your script "module.js" is confusing,
// because node has a built-in module called module...

Module.js

module.exports = {
    "init": function (app, libraries) {
        var key;
        for (key in libraries) {
            if (libraries.hasOwnProperty(key)) {
                this[key] = libraries[key];
                // So you effectively want to copy all properties of libraries
                // to the object in the variable modules in app.js?
            }
        }
        this.oauth.init(app, libraries);
        // I assume the oauth object, required in app.js, also has an init property.
        // So you effectively want to copy all properties of libraries to the modules
        // object and to the oauth object contained in the modules object!?
        // Just pointing out, you're using the same app variable passed in app.js,
        // which in this context is an argument of the module.js .init function.
    }
};

api.js 等等


猜测答案:

init.js

global.api = require('./scripts/api.js');
global.oauth = require('./scripts/oauth.js');
global.db = require('./scripts/db.js');
// Any initialization of required objects is best done when the respective code is
// evaluated, i.e. the first time they're required; Initialization code should be 
// included in respective modules.

app.js

api; // Not available yet!
require('./scripts/init.js');
api; // Refers to the result of require('./scripts/api.js') initialized in init.js
oauth; // idem, etc.

总结:我认为你正在处理一个你不应该处理的问题。对象没有作用域,也没有父对象。对象嵌套形成的属性树是单向的,因为一个对象可以是多个其他对象的属性;所以一般来说,从嵌套对象中检索对嵌套对象的引用是非常不可行的;它需要您编写一个非常精细的搜索函数,执行起来会非常昂贵。如果您想将一个对象的属性复制(推送)到另一个对象 - 无论一个对象是否嵌套在另一个对象中 - 只需制作一个通用的复制功能;您必须明确告诉函数需要将什么复制到什么上。

函数有范围,使用 let 语句块语句可以有范围。对象的花括号不是块语句。

【讨论】:

  • 好主意和明确的解决方案,由于全球。参考,但是我正在尝试以以下方式组织我的项目stackoverflow.com/a/18576246/1752064
  • 我现在将整个 app.js 重构为 // 配置环境 require("./scripts/config.js"); //拉入一些帮助库 global.utils = require("./scripts/utils.js"); global.db = require("./scripts/db.js"); global.account = require("./scripts/account.js"); global.oauth = require("./scripts/oauth.js"); global.api = require("./scripts/api.js"); //拉入我们的路由(哑功能路由器) require("./scripts/routes.js") //拉入我们的视图(哑把手模板) require("./scripts/views.js") 感谢您的帮助
【解决方案2】:

我发现我可以通过在不带 var 关键字的 init 函数中声明它来强制它工作,假设范围是 GLOBAL,这是一种糟糕的做法

http://jsfiddle.net/4wjbyy9g/6/

  this.init = function(libraries)
  {
     for (var key in libraries) {
        var messy = key + " = libraries[key] "

        eval(messy)
     }
     oauth.log('yay!');
  };

可以通过在模块中手动声明变量来避免全局范围问题,但这并不像我想要的那样干净,因为我必须手动声明每个变量名。然而,这是迄今为止我发现的最干净的解决方案

function module()
{
  var oauth = {} //I don't want to have to write this to keep it out of the global scope

  this.init = function(libraries) {
     for (var key in libraries) {
        var messy = "if (typeof " + key + " !== 'undefined') {"
        messy += key + " = libraries[key] }"

        eval(messy)
     }
     oauth.log('yay!');
  }

  this.test = function() {
     oauth.log(JSON.stringify(oauth))     
  }
}

http://jsfiddle.net/52ea5t0q/6/

【讨论】:

  • 不,假定的范围不在对象内,该变量的范围现在是 GLOBAL。
  • @ChrisTavares,天哪,这太糟糕了
  • 我什至不确定“范围在对象内”应该是什么意思。对象没有,也不是范围。范围是函数的一部分。
  • @ChrisTavares 我想你是对的,尽管我对这种情况下的区别有点模糊。这是一个演示我正在尝试做的事情的小提琴我已经确认你是对的,并且在外部函数中没有 var 它将被分配全局范围。我试图避免输入手动函数名称以进行注入jsfiddle.net/52ea5t0q/3
猜你喜欢
  • 2018-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-18
  • 2015-07-09
  • 2022-09-30
  • 1970-01-01
  • 2015-09-18
相关资源
最近更新 更多