开发者

JavaScript losing "this" object reference with private/public properties

开发者 https://www.devze.com 2023-01-08 10:09 出处:网络
I have the following error when running the page below: \"this.testpublic is not a function\" test = function() {

I have the following error when running the page below:

"this.testpublic is not a function"


test = function() {
        var testprivate = function() {
                this.t开发者_StackOverflowestpublic();
        }

        this.testpublic = function() {
                console.log('test');
        }

        testprivate();
}
new test();

Apparently when testprivate is called, "this" starts pointing to "window" instead of the object.

Shouldn't JavaScript preserve "this" context when within the same object?


You need to manipulate the context when calling testprivate. You can use function.call to override the scope of the function. Try this:

test = function() {
        var testprivate = function() {
                this.testpublic();
        }

        this.testpublic = function() {
                console.log('test');
        }

        testprivate.call(this);
}
new test();


The problem is that this actually never was referring to the test object to begin with. It was always referring to the nearest enclosing object -- which in this case is window.

test = function() {
        var testprivate = function(say) {
                console.log('test', say);
        }

        this.testpublic = function(say) {
                testprivate('test', say);
        }

        testprivate();
}
x = new test();

This works because, as I understand it, this is determined at call time -- and it is locked into the nearest "enclosing" object*, unless call() or apply() is used.

* There is probably a much better word for this, but I don't know it off the top of my head. If someone knows, please enlighten us all :-)


No, it shouldn't. The function merely defines scope.

When you call foo.bar() then this (inside bar()) is foo. Since there is no explicit foo in this case, it is window by default.

(this is handled differently when the new keyword is in play, but it isn't for that call)


It is as Sean says: you aren't actually creating a new reference to an object (creating a this context), because you are simply calling the constructor - not utilizing the constructor to create a new object. If you use the new keyword, it works just peachy.

Since the scope of test() is window when you call it, any function called from within test() will execute in the window scope.

By using the new keyword, you are allocating a new object to memory - and creating a new scope.

For example, try this in firebug:

var myFunction = function() {
    this.memberVariable = "foo";
    console.log(this);
}
myFunction();
console.log(window.memberVariable);
var myObject = new myFunction();
console.log(myObject.memberVariable);

You will see this result:

Window stats
foo
Object { memberVariable="foo"}
foo

The Function base object has a method, call(), which as outlined by Craig, allows you to explicitly specify which scope the function should run in:

var myFunction = function() {
    this.memberVariable = "foo";
}
myFunction.call(myFunction);
console.log(myFunction); // "Function()"
console.log(myFunction.memberVariable); // "foo"

This is, however, not the preferred way of doing things, as you aren't actually creating a new object here, and typeof myFunction will still return "function" instead of "object" - when you really just wanted to create an object.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号