javascript - Why do I need to use 'this' to access a value in the map? - Stack Overflow

Consider this code:In the hello function I use this.msg. This works fine. However, it gives a msg unefi

Consider this code:

In the hello function I use this.msg. This works fine. However, it gives a msg unefined error if I don't use this. Why is JavaScript confused, while in many other OO languages this is used only to make code explicit to the reader?

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};

Consider this code:

In the hello function I use this.msg. This works fine. However, it gives a msg unefined error if I don't use this. Why is JavaScript confused, while in many other OO languages this is used only to make code explicit to the reader?

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};
Share Improve this question edited Jul 6, 2013 at 2:51 Rooster 10.1k8 gold badges49 silver badges72 bronze badges asked Jul 6, 2013 at 2:45 Asad IqbalAsad Iqbal 3,3414 gold badges35 silver badges54 bronze badges 7
  • Because smallMap is an object? And personally I feel explicit > implicit :) – Ja͢ck Commented Jul 6, 2013 at 2:50
  • 2 Javascript isn't really OO, it's just faking it by setting this when necessary. – Barmar Commented Jul 6, 2013 at 2:51
  • @Barmar that's a subjective argument, it depends on what you understand OOP to be. – Ja͢ck Commented Jul 6, 2013 at 2:54
  • 1 Is JavaScript Object Oriented? – kojiro Commented Jul 6, 2013 at 2:54
  • Yeah. Every OO language is slightly different in the way they implement accessing instance variables. JS requires you to do it through this. – Barmar Commented Jul 6, 2013 at 2:57
 |  Show 2 more ments

8 Answers 8

Reset to default 3

"Why is JavaScript confused,"

It's not. It has a specific set of rules governing how access to object properties works. It's just that those rules are not the same as every other OO language.

"in many other OO languages this is used only to make code explicit to the reader"

In some OO languages, e.g., Java, this is sometimes used just to make the code explicit to the reader, but really it isn't pletely optional - it is required to distinguish between instance variables (members) and other variables of the same name (e.g., local variables in methods).

JavaScript is object oriented, but it doesn't have classes and doesn't have member methods like some other OO languages such as Java. In JavaScript functions are a type of object and in general terms any variable or object property may be set to reference any function - so even when you define a function inside an object literal like in the question that function isn't owned by the object in question. An example:

function test1() {
    alert('test1');
}
var obj1 = {
    prop1 : 'obj1',
    method1 : test1,
    method2 : function() {
       alert(this.prop1);
    }
}
var test2 = obj1.method2;

obj1.method1();                 // alerts 'test1'
test1();                        // alerts 'test1'
obj1.method2();                 // alerts 'obj1'
test2();                        // alerts undefined (probably; see note below)
test2.call({prop1 : 'test2'});  // alerts 'test2'
delete obj1.method2;            // remove the property
alert(obj1.method2);            // alerts undefined - property no longer exists
test2.call({prop1 : 'test2'});  // alerts 'test2' - the function still exists

Notice that obj1.method1 references a function defined outside the literal, a function that can be called directly with test1(). Similarly, test2 has been set to refer to a function that has been defined in the literal but can be called directly - even if you actually remove the method2 property you can still call test2() directly.

I defined method2 / test2 so that it uses this.prop1. The value of this is set depending on how a function is called. If you call it with "dot" notation, like obj1.method2() then within the function this will be the object before the dot. If you call the function directly like test2() then in non-strict mode this would be window, but in strict mode may be undefined or some other value - see MDN for more details. Or you can call a function with .call() or .apply() and explicitly set this to some other object, like in the example above.

Because this is special in Javascript and doesn't always apply to the same object. For example I could do this:

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};

var smallMap2 = {
    msg: "Hellow2 ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};
//here i set `this` to refer to `smallMap2` within smallMap
smallMap.hello.call( smallMap2, "the name" );
//will print "Hellow2 the name" instead of "Hellow the name"

this refers to the object that the function is being called on and not the necessarily the object that the function is a property of. See this for more details:

https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Operators/this

Also take a look at call, apply, and bind for more info related to this.

In Javascript, it's impossible to statically determine what properties this has. The msg property could be deleted, or the hello method could be attached to a new object or called as an ordinary function. Thus, Javascript has to assume that an unqualified identifier refers to a variable instead of an object property, even if the object happens to have a property with the right name. It's possible to force Javascript to look in the object properties with a with statement, but because you can't tell what the properties are, this is generally considered a horrible idea.

What you have created is an object (or at least as far as JS is concerned). When you want to access the objects own properties, you will need to use the this keyword.

An object in JS is simply a collection of variables and functions. When you want to use the objects own variables inside it, you will need to use this. You have created this object by using {} or curly-braces in the definition of the object.

Outside the confines of the object, you will need to use, <objectName>.var_or_func.

What you have coded is not a class, but an object.

The word this in javascript is related to the scope and not to the object that this peace of code is in.

You could get something like you want by doing this:

var smallMap = (function(){
    var msg = "Hellow ";

    return {
        hello : function(name) {
            console.log(msg + name);
        }
    }   

})();

That said you also can't use this.msg. Just try it out and you will see.

Since Javascript is not really object-oriented (it is prototypical, meaning, objects can inherit directly from other objects), things doesn't work quiet the same as OO from scoping perspective:

Let's take your example, and use it to inherit the "hello" function by another object:

var new_obj;
new_obj.hello = smallMap.hello;

There, now another object has the same function. Alas, when this function will be called on new_obj, for example:

new_obj.hello("test");

unless we define new_obj.msg, we'll get undefinedtest.

So here we should be careful: what do we really want ? to use the new_obj.msg or to always use smallMap.msg. If the answer is the latter, we should be using smallMap.msg instead of this.msg inside function hello. TMHO of course...

Using object literals ({ ... }) is not the same as defining a class. The scope for the "hello" function is the same as if you defined it externally, e.g., smallMap.hello = function() { ... }.

The reason for this is so that you can write arg1.func(arg2, arg3) and refer to arg1 as this within the definition of func, instead of writing func(arg1, arg2, arg3). this is resolved dynamically unlike other variables which are resolved statically (which is why you can't access msg without it). It's there to facilitate dot notation for calling 'methods', and it's there as a fort blanket for Java developers. (Although since JavaScript doesn't have function overloading, x.f(y,z) gives you useful namespacing for function f.)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745122577a4612500.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信