最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Changing JavaScript's global object? - Stack Overflow

programmeradmin6浏览0评论

Is there a way to change the root object in JavaScript?

For example, in browsers, the root object is "window". So

X = 5;
console.log(Y);

is the same as:

window.X = 5;
console.log(window.Y);

What I want to do now, is changing this root object, so when I do the following:

X = 6;

Reason why I need this:

In Node.js applications, every part of the program can access the global object. That's a big problem because every script that is executed by a Node.js webserver can add new variables to it. They will be there until the webserver is restarted. I want to avoid this by changing the global object.

Update

I've tested the following code and got a really interesting result. What did you expect of the following code?

var X = {A:"a",B:"b"};

with(X){
    A = 5;
    C = 7;
}
for(a in X){
    console.log(a+" is "+X[a]);
}

/* 
Expected Console Output:
A is 5
B is b
C is 7

Real Console Output:
A is 5;
B is b;

*/

Is there a way to get output as I expected it?

Update

I've now tested the module system with the following code.

//program.js
var t = require("./module.js");
t.Test();

console.log(A);

//module.js
A = 5;
exports.Test = function(){
    console.log("hello world!");
}

The output was:

hello world!
5

This tells me, that the variable "A" defined in module.js was added to the global object of program.js. The module does not solve my problem, either.

Is there a way to change the root object in JavaScript?

For example, in browsers, the root object is "window". So

X = 5;
console.log(Y);

is the same as:

window.X = 5;
console.log(window.Y);

What I want to do now, is changing this root object, so when I do the following:

X = 6;

Reason why I need this:

In Node.js applications, every part of the program can access the global object. That's a big problem because every script that is executed by a Node.js webserver can add new variables to it. They will be there until the webserver is restarted. I want to avoid this by changing the global object.

Update

I've tested the following code and got a really interesting result. What did you expect of the following code?

var X = {A:"a",B:"b"};

with(X){
    A = 5;
    C = 7;
}
for(a in X){
    console.log(a+" is "+X[a]);
}

/* 
Expected Console Output:
A is 5
B is b
C is 7

Real Console Output:
A is 5;
B is b;

*/

Is there a way to get output as I expected it?

Update

I've now tested the module system with the following code.

//program.js
var t = require("./module.js");
t.Test();

console.log(A);

//module.js
A = 5;
exports.Test = function(){
    console.log("hello world!");
}

The output was:

hello world!
5

This tells me, that the variable "A" defined in module.js was added to the global object of program.js. The module does not solve my problem, either.

Share Improve this question edited Nov 28, 2016 at 16:32 Tim Perry 13.2k2 gold badges67 silver badges91 bronze badges asked Feb 19, 2011 at 18:13 Van CodingVan Coding 24.6k25 gold badges92 silver badges137 bronze badges 2
  • 2 Proper term is not ROOT but Global, in browsers window implements Global – Free Consulting Commented Feb 19, 2011 at 19:08
  • If you use "use strict"; on top of your code, your example is not possible. I came here because I want to do the same, actually I want to replace the global object with a proxy object. This is working fine however lost it's global scope. I think it has something to do with a reference to the old object. – Codebeat Commented Aug 13, 2018 at 16:00
Add a ment  | 

3 Answers 3

Reset to default 8

There is the with statement, but it is not remended and forbidden in strict mode.

It is better to refer to the variable holding the object explicitly.

In response to updated question:

with will search up the scope chain until it finds an object with a matching property or gets to window. It is no good for defining new properties on an object.

var X = { A: 5, B: 8, C: 7};
with(X){
    console.log(A, B, C);
}

If you're talking about variables, JavasScript has function scope.

X = 5;  // global variable

console.log( window.X );  // 5

(function() {
   var X = 6;  // declare a local variable by using the "var" keyword

   console.log( X );  // 6
})();

console.log( window.X );  // 5

Otherwise, you can create an Object, and add properties to it.

X = 5; 

console.log( window.X );  // 5

var obj = {};

obj.X = 6;

console.log( obj.X ); // 6

console.log( window.X );  // 5

EDIT: Adding another possible solution that could be used.

You could invoke an anonymous function, but set the context of the function to your X object. Then this in the function will refer to X.

var X = {};
(function(){
    this.A = 5;
    this.B = 8;
    this.C = 7;
}).call(X);
for(a in X){
    console.log(a+" is "+X[a]);
}

The .call() method (as well as the .apply() method) allow you to explicitly set the thisArgof a calling context. The first argument you pass will be howthis` is defined in the context of the invocation.

Or just pass X in as an argument.

var X = {};
(function(X){
    X.A = 5;
    X.B = 8;
    X.C = 7;
})(X);
for(a in X){
    console.log(a+" is "+X[a]);
}

Though the simplest is to simply reference it (as I noted in my answer above).

var X = {};
X.A = 5;
X.B = 8;
X.C = 7;
for(a in X){
    console.log(a+" is "+X[a]);
}

or use a module pattern:

   /****** I'm guessing at the use of "global" here ********/
global.myNamespace = (function(global,undefined) {

    // define the object to be returned
    var X = {};

    //  define private local variables
    var a_local = 'some value';
    var another_local = 'some other value';

    // define private functions
    function myFunc() {
        // do something with local variables
    }

    // give the return object public members
    X.someProperty = 'some value';
    X.anotherProperty = 'another value';
    X.publicFunc = function() {
        //do something with the local variables
        //    or public properties
    };
    X.anotherFunc = function() {
        //do something with the local variables
        //    or public properties
    };
    // return the object
    return X;

})(global);

console.log(myNamespace);

I found a way in EcmaScript 6 to adjust with(context) { ... }, so that any new variables we assign will go into the context object, not the global / window object.

Thanks to this article Metaprogramming in ES6: Part 3 - Proxies for teaching me about the ES6 Proxy feature.

In the proxy:

  • We override has to return true, so our context appears to have all properties, and when we set any variable it will go to the object.
  • We override get to get the property from our context, or if it isn't really there, we get the property from an up object (which defaults to the global window).

I know that with is frowned upon, but this technique enables to create mutable extensible modules where we can access members conveniently as foo rather than Module.foo, and I don't think it is unsafe or ambiguous.

function scope(x, up=window) {
    return new Proxy(x, {
        has: (o, k) => true,
        get: (o, k) => k in o ? o[k] : up[k]
    });
}

var Test = {};

with (scope(Test)) {
    x = 1;
    y = 2;
    add_x = function(y) {
        console.log(x + y);
    }
}

Test.add_x(10);

with (scope(Test)) {
    x = 3;
    add_y = function(x) {
        console.log(x + y);
    }
}

Test.add_x(20);

Test.y = 5;

Test.add_y(30);

发布评论

评论列表(0)

  1. 暂无评论