The right way to 'call' a class attribute inside the same class

Thomas 'PointedEars' Lahn PointedEars at web.de
Mon Dec 19 08:16:44 EST 2016


Chris Angelico wrote:

> On Mon, Dec 19, 2016 at 9:52 AM, Erik <python at lucidity.plus.com> wrote:
>> 1) Method call:
>>    "obj.foo(1, 2, 3)" is syntactic sugar for "obj.foo(obj, 1, 2, 3)".
> 
> And the bit you have to be REALLY careful of when working with both
> Python and JS is that you have to have "obj.foo(...)" as a single
> expression. Consider:
> 
> # Python
> lst = []
> func = lst.append
> func(1); func(2); func(3)
> # lst now holds [1,2,3]
> 
> // JavaScript
> var arr = []
> var func = arr.push.bind(arr) // IMPORTANT
> func(1); func(2); func(3)
> // arr now contains [1,2,3]
> 
> If you just take "arr.push", you don't get a bound method. You get an
> unbound method. You have to explicitly bind that back to the array
> object, or its "this" pointer won't be set.

“this” is not a pointer, it is a built-in variable (adj.) *value*.  There 
are no (high-level) pointers in implementations of ECMAScript (there may be 
in the language used to *build* the *implementation*, e.g. C++).  Instead, 
there are reference values referring to objects.

With func(…), “this” would be set to a reference to the global object in 
non-strict mode, and to “undefined” in strict mode.

But the question here is: Why would one insist to declare a (global) 
variable, and assign to it a reference to the Array.prototype.push() method 
instead of calling the “push” method directly, accessed through the 
prototype chain?  *This* certainly is _not_ how you should do this in 
ECMAScript implementations, but instead:

  /* arr now contains [1,2,3] */
  arr.push(1, 2, 3);

Because “this” is *always* set to a reference to the calling (or 
constructed) object, if any (if there is no explicit object, it depends on 
the execution mode; see above).

At best, yours is a bad example following a misconception.
 
> This is so important (eg with callback functions) that JS introduced a
> new type of function to help deal with the problem...

Or because "JS" is “the world’s most misunderstood programming language” 
(Crockford, and I agree with him on *that*), as ISTM you just demonstrated.

There is no “new type of function”.  Using Function.prototype.bind() this 
way (it is not available in implementations of ECMAScript Ed. 4 and earlier) 
is functionally equivalent to

  func.call(arr, …, …);

aso.  It is syntactic sugar so that you can write

  var func2 = func.bind(this);
  func2(…);

and do not have to write, e.g.,

  var that = this;
  var func2 = function () {
    func.call(that, …, …);
  };
  func2(…);

but it is not necessarily more efficient than a simple call of 
Function.prototype.call() or Function.prototype.apply().

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.



More information about the Python-list mailing list