开发者

Still confused about JavaScript's 'this'

开发者 https://www.devze.com 2022-12-28 05:41 出处:网络
I\'ve been reading through quite a few articles on the \'this\' keyword when using JavaScript objects and I\'m still somewhat confused. I\'m quite happy writing object orientated Jav开发者_JAVA百科asc

I've been reading through quite a few articles on the 'this' keyword when using JavaScript objects and I'm still somewhat confused. I'm quite happy writing object orientated Jav开发者_JAVA百科ascript and I get around the 'this' issue by referring the full object path but I don't like the fact I still find 'this' confusing.

I found a good answer here which helped me but I'm still not 100% sure. So, onto the example. The following script is linked from test.html with <script src="js/test.js"></script>

if (!nick) {
    var nick = {};
}

nick.name= function(){
    var helloA = 'Hello A';
    console.log('1.',this, this.helloA);

    var init = function(){
        var helloB = 'Hello B';
        console.log('2.',this, this.helloB);
    }

    return {
        init: init
    }
}();

nick.name.init();

What kind of expected to see was

1. Object {} nick.name, 'Hello A'
2. Object {} init, 'Hello B'

But what I get is this?

1. Window test.html, undefined
2. Object {} init, undefined

I think I understand some of what's happening there but I would mind if someone out there explains it to me.

Also, I'm not entirely sure why the first 'console.log' is being called at all? If I remove the call to the init function //nick.name.init() firebug still outputs 1. Window test.html, undefined. Why is that? Why does nick.name() get called by the window object when the html page loads?

Many thanks


Also, I'm not entirely sure why the first 'console.log' is being called at all?

nick.name = function(){
    // ...
}();

Here you define a function, call it immediately (hence ()) and assign its return value ({init: init}) to nick.name

So the execution is:

  1. Create a variable called nick if there isn't one with a non-falsey value already
  2. Create an anonymous function that…
  3. Creates a variable called helloA in its own scope
  4. Outputs data using console.log containing "1" (as is), this (the window because the function is executing in the global context instead of as a method), and this.helloA (window.helloA, which doesn't exist.
  5. Defines a function called init
  6. Returns an object which gets assigned to nick.name
  7. Then you call nick.name.init() which executes the init function in the context of name.
  8. This defines helloB
  9. Then it console.logs with "2" (as is), this (name), and this.helloB (nick.name.helloB - which doesn't exist)

So the first output you get is from console.log('1.',this, this.helloA);

I think your main problem is that you are confusing this.foo (properties on the object on which a method is being called) with variable scope (variables available to a function)


It's much simpler if you think about this as a function, not as a variable. Essentially, this is a function which returns current "execution context", that is, the object the current function was "applied" to. For example, consider the following

function t() { console.log(this)}

this will return very different results depending upon how you call it

t() // print window

bar = { func: t }
bar.func() // print bar

foo = { x: 123 }
t.apply(foo) // print foo


  1. this is defined on a per-function basis when the function call is made. When you call a function as o.f(), this will be o within the function, and when you call it as f(), this will be the global object (for browsers, this is the window). You wrote nick.name = function(){...}(); and the right-hand part is of the form f(), hence the Window.

  2. var foo = bar; defines a local variable. It may not be accessed as this.foo (well, except when you're at global scope, but that's silly). To define a member, you usually write this.foo = bar; instead.


This is what your code does:

  • It creates an object and assigns to the variable nick.
  • It creates an anonymous function.
  • It calls the function (in the window scope).
  • It assigns the return value (an object containing the init property) to the name property of the object.
  • It gets the value from the init property, which is a method delegate, and calls the method.

The anonymous function does this:

  • It declares a local variable named helloA and assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.)
  • It logs this (window) and the helloA property (which doesn't exist).
  • It creates an anonymous function and assignes to the local variable init.
  • It creates an object with the property init and the value from the local variable init.

The anonymous function assigned to the init property does this:

  • It declares a local variable named helloB and assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.)
  • It logs this (the object from the name property, not the nick variable), and the helloB property (which doesn't exist).
0

精彩评论

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