Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

80%
+6 −0
Q&A Function call; `this` gets bound to unexpected value

This MDN link might help to explain that: When a function is called as a method of an object, its this is set to the object the method is called on. Which is your first example (calling obj.a())....

posted 3y ago by hkotsubo‭  ·  edited 3y ago by Alexei‭

Answer
#7: Post edited by user avatar Alexei‭ · 2020-10-25T16:08:55Z (over 3 years ago)
removed the inappropriate picture
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did, and create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() { return (this === obj) ? this.b : 'bye'; },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, using "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that uses "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls `GetThisEnvironment`, [whose definition says](https://tc39.es/ecma262/#sec-getthisenvironment): "*It finds the Environment Record that currently supplies the **binding** of the keyword `this`*".
  • So I guess "_binding_" would be an appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did, and create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() { return (this === obj) ? this.b : 'bye'; },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, using "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that uses "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls `GetThisEnvironment`, [whose definition says](https://tc39.es/ecma262/#sec-getthisenvironment): "*It finds the Environment Record that currently supplies the **binding** of the keyword `this`*".
  • So I guess "_binding_" would be an appropriate term.
#6: Post edited by user avatar hkotsubo‭ · 2020-09-01T19:12:01Z (over 3 years ago)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did, and create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, using "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls `GetThisEnvironment`, [whose definition says](https://tc39.es/ecma262/#sec-getthisenvironment): "*It finds the Environment Record that currently supplies the **binding** of the keyword `this`*".
  • So I guess "_binding_" would be an appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did, and create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() { return (this === obj) ? this.b : 'bye'; },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, using "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that uses "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls `GetThisEnvironment`, [whose definition says](https://tc39.es/ecma262/#sec-getthisenvironment): "*It finds the Environment Record that currently supplies the **binding** of the keyword `this`*".
  • So I guess "_binding_" would be an appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
#5: Post edited by user avatar hkotsubo‭ · 2020-09-01T19:09:25Z (over 3 years ago)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did, and create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, using "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls `GetThisEnvironment`, [whose definition says](https://tc39.es/ecma262/#sec-getthisenvironment): "*It finds the Environment Record that currently supplies the **binding** of the keyword `this`*".
  • So I guess "_binding_" would be an appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
#4: Post edited by user avatar hkotsubo‭ · 2020-09-01T19:06:48Z (over 3 years ago)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish that behaviour of "preserving" `this`, you could use `bind` or `call`, which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish the behaviour of "preserving" `this`, you could use [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) or [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
#3: Post edited by user avatar hkotsubo‭ · 2020-09-01T19:02:19Z (over 3 years ago)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish that behaviour of "preserving" `this`, you could use `bind` or `call`, which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish that behaviour of "preserving" `this`, you could use `bind` or `call`, which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • ![JS this is confusing](https://software.codidact.com/uploads/CEtdDJedzP2KRQag3UqjgUqa)
#2: Post edited by user avatar hkotsubo‭ · 2020-09-01T19:00:54Z (over 3 years ago)
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
  • [This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:
  • > _When a function is called as a method of an object, its `this` is set to the object the method is called on._
  • Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:
  • ```javascript
  • let obj = {
  • b: 'hello'
  • };
  • function f() {
  • return (this === obj) ? this.b : 'bye';
  • }
  • obj.a = f;
  • console.log(obj.a()); // hello
  • console.log(f()); // bye
  • ```
  • That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.
  • BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function, and `obj.a === (obj.a)` is `true`). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.
  • To accomplish that behaviour of "preserving" `this`, you could use `bind` or `call`, which are two ways of controlling which value of `this` the function sees:
  • ```
  • let obj = {
  • a: function() {
  • return (this === obj) ? this.b : 'bye';
  • },
  • b: 'hello'
  • };
  • let a = obj.a;
  • console.log(a()); // bye
  • // with call, use "obj" as the "this" value
  • console.log(a.call(obj)); // hello
  • // bind, returns another function that use "obj" as the "this" value
  • let boundFunc = obj.a.bind(obj);
  • console.log(boundFunc()); // hello
  • ```
  • ---
  • I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".
  • So I guess "binding" would be the appropriate term.
#1: Initial revision by user avatar hkotsubo‭ · 2020-09-01T18:55:23Z (over 3 years ago)
[This MDN link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method) might help to explain that:

> _When a function is called as a method of an object, its `this` is set to the object the method is called on._

Which is your first example (calling `obj.a()`). But the link above also mentions that "*this behavior is not at all affected by how or where the function was defined*". So I could do the opposite of what you did: create the function outside the object and then attach it:

```javascript
let obj = {
  b: 'hello'
};

function f() {
    return (this === obj) ? this.b : 'bye';
}

obj.a = f;
console.log(obj.a()); // hello
console.log(f()); // bye
```

That's because what really matters is **how** you invoke the function. If called from a member of the object, the `this` value is set to the object, regardless of where the function was defined. So calling it in a "non-object" context doesn't set `this` to the object.

BTW, calling `(obj.a)()` is the same as `obj.a()` because in this case the first pair of parenthesis is redundant (`(obj.a)` evaluates to the `obj.a` function). But it's not the same as setting a variable `f = obj.a` and then calling `f()` because, as said above, how the function is called influences the value of `this`, and by calling `f()`, I'm not invoking the function as a method of an object.

---
I'm not sure about the exact terminology, but [this section of the spec](https://tc39.es/ecma262/#sec-this-keyword-runtime-semantics-evaluation) mentions the `ResolveThisBinding` operation, [whose definition says](https://tc39.es/ecma262/#sec-resolvethisbinding): "*It determines the **binding** of the keyword `this` using the LexicalEnvironment of the running execution context.*" - and `ResolveThisBinding` operations calls [`GetThisEnvironment`](https://tc39.es/ecma262/#sec-getthisenvironment), whose definition says: "*It finds the Environment Record that currently supplies the binding of the keyword `this`*".

So I guess "binding" would be the appropriate term.