Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I assign a new value to "this" in a prototype function?

Tags:

javascript

Why can I do this:

Array.prototype.foo = function() {     this.splice(0, this.length);     return this.concat([1,2,3]); } 

But I can't do this:

Array.prototype.foo = function() {     return this = [1,2,3]; } 

Both functions destroy the value of this and change it to [1,2,3] but the second one throws the following error: Uncaught ReferenceError: Invalid left-hand side in assignment

I suspect it's because allowing assignment means I could potentially change the array to something else (like a string), but I'm hoping someone out there knows for sure and/or has a more detailed explanation.

like image 341
Philip Walton Avatar asked Mar 15 '12 02:03

Philip Walton


People also ask

Can you assign a value to a function?

No, you can't assign values to functions.

Why this keyword is undefined in JavaScript?

A variable that has not been assigned a value is of type undefined . A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value. A function returns undefined if a value was not returned. Let's try to understand by a simple example.

What does the this keyword indicate in JavaScript?

In JavaScript, the this keyword refers to an object. Which object depends on how this is being invoked (used or called). The this keyword refers to different objects depending on how it is used: In an object method, this refers to the object.

What does .prototype do in JavaScript?

The prototype is an object that is associated with every functions and objects by default in JavaScript, where function's prototype property is accessible and modifiable and object's prototype property (aka attribute) is not visible. Every function includes prototype object by default.


2 Answers

You're confusing objects with references.

An array is an object, when you use a literal like [1,2,3] you're making a new array.

A variable name like this or a is a reference to an object. If it helps, imagine an object as a person, and the reference as their nickname. You can have more than one reference to the same object, for example:

var a = [1,2]; var b = a; b.push(3); alert(a.length); // Gives "3" 

Imagine if you had a friend named Sarah. You also sometimes call her "Ace". If Sarah gets a haircut one day, Ace has a haircut too, because "Sarah" and "Ace" are both different names for the same person.

If you use a mutating array method like a.push or a.splice (concat however is not one!), you change the existing Array object, and a still refers to the same object. This is like getting a hair cut - you may look different, but you're still the same person.

When you assign a reference to a new value, with a = [1,2,3], you're creating a new array, and changing a to refer to it. This is like finding a new friend with different hair, and deciding to call her Ace instead.

Now this is a special name generated by Javascript. It's not a given name like Sarah, but more of a title, like "mother". Your mother can get a new haircut, but you can't get a new mother. Likewise, you can't change what this refers to from inside a function.

like image 190
Tobias Cohen Avatar answered Oct 10 '22 02:10

Tobias Cohen


It's not permitted to assign a value to this within a function. Suppose that you could do this, and your code looked something like:

Array.prototype.foo = function() {     return this = [1, 2, 3]; }  var a = ["beans", "rice"]; a.foo(); // a now points to an object containing [1, 2, 3] 

Now, what if you did this:

var a = ["beans", "rice"]; var b = a; // b refers to the same object as a b.foo(); // what does b refer to now? how about a? 

The act of calling a function .foo() on an object should not change the identity of the object. This would be very confusing for the caller if b suddenly started referring to a different object than a simply because some method was called.

like image 28
Greg Hewgill Avatar answered Oct 10 '22 02:10

Greg Hewgill