Why can't I assign a new value to this in a prototype function?
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. changing value in prototype does not work in JavaScript
As commented, the leg you are trying to access is a self owned property and not on prototype.
Following is a sample:
function Animal() { this.legs = 4;}Animal.prototype.legs = 8;var mouse = new Animal();
mouse.legs = 2;console.log(mouse.legs, mouse.__proto__.legs);
Add value using prototype in function instance
It should be a prototype of the constructor function, not the object this function produces:
a.prototype.three = 3;
You can't access object's prototype with the prototype
key, because prototype reference is not exposed like this. You could do it using __proto__
property though, but this is deprecated. If you need to get a prototype of the object you can make use of Object.getPrototypeOf
method:Object.getPrototypeOf(j) === a.prototype; // true
It's a little confusing here because the word "prototype" sort of means two things. Function prototype is an object that is used when new object is constructed when the function is used like a constructor. Object prototype is a reference to the object which stores inherited methods. Assigning prototype methods *inside* the constructor function - why not?
Yes, there are drawbacks and unexpected scoping issues.Functionally, are there any drawbacks to structuring my code this way?
Will adding a prototypical method to a prototype object inside the
constructor function's body (i.e. before the constructor function's
expression statement closes) cause unexpected scoping issues?
Assigning the prototype over and over to a locally defined function, both repeats that assignment and creates a new function object each time. The earlier assignments will be garbage collected since they are no longer referenced, but it's unnecessary work in both runtime execution of the constructor and in terms of garbage collection compared to the second code block.
There are unexpected scoping issues in some circumstances. See the
Counter
example at the end of my answer for an explicit example. If you refer to a local variable of the constructor from the prototype method, then your first example creates a potentially nasty bug in your code.
Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)
And, of course, if someone used:Object.create(Filter.prototype)
without running the Filter
constructor, that would also create a different result which is probably not as likely since it's reasonable to expect that something that uses the Filter
prototype should run the Filter
constructor in order to achieve expected results.From a run-time performance point of view (performance of calling methods on the object), you would be better off with this:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
this.checkProduct = function( product ){
// run some checks
return is_match;
}
};
There are some Javascript "experts" who claim that the memory savings of using the prototype is no longer needed (I watched a video lecture about that a few days ago) so it's time to start using the better performance of methods directly on the object rather than the prototype. I don't know if I'm ready to advocate that myself yet, but it was an interesting point to think about.The biggest disadvantage of your first method I can think of is that it's really, really easy to make a nasty programming mistake. If you happen to think you can take advantage of the fact that the prototype method can now see local variables of the constructor, you will quickly shoot yourself in the foot as soon as you have more than one instance of your object. Imagine this circumstance:
var Counter = function(initialValue){
var value = initialValue;
// product is a JSON object
Counter.prototype.get = function() {
return value++;
}
};
var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get()); // outputs 10, should output 0
Demonstration of the problem: http://jsfiddle.net/jfriend00/c7natr3d/This is because, while it looks like the get
method forms a closure and has access to the instance variables that are local variables of the constructor, it doesn't work that way in practice. Because all instances share the same prototype object, each new instance of the Counter
object creates a new instance of the get
function (which has access to the constructor local variables of the just created instance) and assigns it to the prototype, so now all instances have a get
method that accesses the local variables of the constructor of the last instance created. It's a programming disaster as this is likely never what was intended and could easily be a head scratcher to figure out what went wrong and why.
Why can't I set the 'prototype' of a function created using 'bind'?
Well, there are exceptions to every rule :-) You found one: bound functions don't have aAs I understood, every function has a prototype object.
.prototype
property because they don't need it. When you call a bound function with new
, it calls the original function as a constructor, using the original's .prototype
object as the prototype of the new instance.In fact, since ECMAScript 6 many functions don't have a .prototype
property with an object, because they are not constructors - they cannot be called with new
so they don't need it. Among those are
- arrow functions (
() => {…}
) - methods (
method() { … }
in object literals and classes) - builtin non-constructor functions (like
Math.sin
)
Can't assign this in constructor
You could extend this
with Object.assign method:
class Foo {
constructor (props) {
Object.assign(this, props);
}
}
const foo = new Foo({ a: 1 });
console.log(foo.a); // 1
Can't add method prototype to JavaScript object
Returning an object circumvents the usual return value of a constructor, which is the this
variable. Instead of returning this
, you're returning some other object, and that object doesn't have a username property or a method_name method. This is roughly what happens at each point in the code:
function User(un) {
this.username = un; // puts username on the 'this' object
// returns an entirely different, unrelated object that doesn't use User's prototype
return{
getUsername: function (){
return un;
},
setUsername: function(username) {
un = username;
}
};
}
// sets method_name on the prototype of the 'this' object for User
User.prototype.method_name = function() {
return this.username;
};
var user = new User("Michael"); // passes a new User.prototype as the implicit 'this' in the User function
console.log(user.method_name());
Instead, try this:function User(un) {
this.username = un;
this.getUsername = function (){
return un;
};
this.setUsername = function(username) {
un = username;
};
}
User.prototype.method_name = function() {
return this.username;
};
Related Topics
Jquery Returning "Parsererror" for Ajax Request
Why Does a Simple .*? Non-Greedy Regex Greedily Include Additional Characters Before a Match
Return Index of Greatest Value in an Array
JavaScript Ternary Operator Example with Functions
Finding "Line-Breaks" in Textarea That Is Word-Wrapping Arabic Text
I Can't Reference an Image in Next.Js
How to Getting Browser Current Locale Preference Using JavaScript
Why a Variable Defined Global Is Undefined
Get Unique Results from JSON Array Using Jquery
How to Parse a Date in Format "Yyyymmdd" in JavaScript
How to Export Socket.Io into Other Modules in Nodejs
Regular Expression for Ip Address Validation
Start HTML5 Video at a Particular Position When Loading
How to Update a Specific Index from the Array in Firestore
Using Fetch API to Access JSON