0

Here is the code

function SuperType(){
    this.property = 'aa';
}

SuperType.prototype.property='aaa'

SuperType.prototype.getSuperValue = function(){
    console.log("this===s : "+(this===s))
    console.log("this===SuperType.prototype : "+(this===SuperType.prototype))
    return this.property;
}



var s=new SuperType();
console.log(s.getSuperValue())

My question is why this in getSuperValue refer to s ? In a normal sense,it should refer to 'SuperType.prototype'.

At first glance, getSuperValue() is called by s ,so this in getSuperValue scope should refer to s. However s.getSuperValue is actually s.__proto__.getSuperValue() that is why I think this in getSuperValue refer to SuperType.prototype

==========================================

I studied all the answers in How does the "this" keyword work? and failed to find anything explain the question

I real reason is s.getSuperValue() <=> Object.getPrototypeOf(s).getSuperValue.call(s) while I wrongly regard it as s.getSuperValue() <=> Object.getPrototypeOf(s).getSuperValue()

To those who concerns ,just put the answer here

===============================================

Got some new understanding of this issue

even though the function reside in prototype

console.log(s.getSuperValue===s.__proto__.getSuperValue) //true

The lookup process is not related to how this is bound

console.log(s.getSuperValue()) // 'aa'
console.log(s.__proto__.getSuperValue()) //'aaa'

this is only determined exclusively by where the function is called

=================== update ================

A more demonstrating example :

function merge(a, b){
    if (a && b) {
        for (var key in b) {
            a[key] = b[key];
        }
    }
    return a;
};
var a={hello:"world"}

var aa={hi:function () {
    console.log(this.hello)
}}
var aaa=merge(a,aa)
aaa.hi()
Community
  • 1
  • 1
Guichi
  • 1,442
  • 1
  • 11
  • 22
  • When you call a method as `s.methodname()`, `this` is always `s`. – Barmar Aug 22 '16 at 01:03
  • 2
    It depends on the call, not where the function is defined. The function itself doesn't even know that it's been assigned to a property of `SuperType.prototype`. – Bergi Aug 22 '16 at 01:04
  • @Bergi if 'The function itself doesn't even know that it's been assigned to a property of SuperType.prototype' `s.getSuperValue()` should return `undefined` – Guichi Aug 22 '16 at 01:09
  • @Bergi I think I know what you mean,but consider: s.getSuperValue() <=> s.__prototype__.getSuperValue() so `this` in `getSuperValue()` should refer to `s.__prototype__.` rather than `s` which is equivalent to `SuperType.prototype` – Guichi Aug 22 '16 at 01:17
  • 1
    @Guigui Well, no, that's not exactly how it works. It's `s.getSuperValue()` <=> `Object.getPrototypeOf(s).getSuperValue.call(s)` - the syntax of the property access is what matters for the function to be invoked as a method of the receiver. Not where the property is eventually found. – Bergi Aug 22 '16 at 01:26
  • @Bergi thanks, you are a expert ! So the real reason is `.call(s)` bound `this` magically .Is there some comprehensive reference for this. I works with javascript for almost a year, never know this before – Guichi Aug 22 '16 at 01:34
  • Have a look at the answers to the duplicate question, and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#Function_context – Bergi Aug 22 '16 at 01:43
  • @Bergi .In fact,I can not see why it is duplicated,I walked through the mozilla document ,it not mention how `this` in `prototype` work at all.Also ,I studied the stackoverflow thread .One of the answer mention `this` in `prototype` ,It just provide some fact,can not explain why `this` refer to instance rather than the prototype. I even think he/she also misunderstand the mechanism So `Object.getPrototypeOf(s).getSuperValue.call(s)` is a really good point and deserve to share – Guichi Aug 22 '16 at 01:58
  • @Barmar ,consider reopen it if you think it is not duplicated – Guichi Aug 22 '16 at 03:02
  • @Guigui I marked it as a duplicate of http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript?noredirect=1&lq=1. Someone else reopened it and closed it as a duplicate of a different question. – Barmar Aug 22 '16 at 03:05
  • @Barmar ,I think these answers can not explain why `this` in `instance.__proto__.method` refer to `instance` directly bypassing `instance.__proto__` ,I think the real reason is as Begri point out, Javascript engine do some magic thing internally which is in contrary to the normal way JS work, that is why I request a reopen – Guichi Aug 22 '16 at 03:29
  • 1
    The instance is always whatever is before the `.` in the function call. It doesn't matter if the function is retrieved from the object itself or from the prototype. – Barmar Aug 22 '16 at 03:34
  • @Barmar it is easy to get confuse that the thing before `.` is `instance.__proto__` rather than `instance` if you consider where the method 'really' called.However,the JS implementation do some tricks to break this rule in these cases enabling the statement 'The instance is always whatever is before the . in the function call' always hold – Guichi Aug 22 '16 at 03:41
  • 1
    The method is **really** called when you write `s.GetSuperValue()`. The only thing the prototype is used for is to look up the value of the `GetSuperValue` property. Just because the function is in the prototype doesn't mean it actually calls `s.__proto__.GetSuperValue()`. – Barmar Aug 22 '16 at 03:44
  • @Barmar ,do you mean `GetSuperValue` is in object itself ,prototype mechanism is just a way for lookup up ?If so,I can argue that `GetSuperValue` has nothing to do with the `s` because it is share by all instance,not exclusively `s`, I think `GetSuperValue` should be in a seperate object not `s` – Guichi Aug 22 '16 at 03:50
  • @Barmar the point is if a property define constructor ,it is exclusive for the new object,but if it reside in prototype,it should be share ,and have a different memory allocation than the new object, `proto` is just a means to lookup the seperate object – Guichi Aug 22 '16 at 03:54
  • The point is that it doesn't matter where the property is found, in the object or the prototype. The context is based on the syntax used to call it, not where it's found. – Barmar Aug 22 '16 at 03:54
  • @Barmar ,right , how `this` work just a syntax rule ,not necessary bound to how it implemented – Guichi Aug 22 '16 at 03:57
  • 1
    Exactly. And I think that is explained in the related questions. – Barmar Aug 22 '16 at 03:58
  • Maybe you should read the linked stuff again. Both [this answer](http://stackoverflow.com/a/17514482/1048572) as well as the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#this_on_the_object's_prototype_chain) do include an section especially about methods inherited from the prototype. And yes, the prototype chain is merely a lookup mechanism, the call is still `s.getSuperValue()` **on `s`** - and if it weren't for that, prototype methods wouldn't work at all because they couldn't access the instance. – Bergi Aug 22 '16 at 12:21

0 Answers0