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