Let us say we have a function.
function Rabbit(){
console.log("shiv");
}
Now without creating an object of this function i can assign the property of this object
Rabbit.bark = function(line) {
console.log("name is", line);
};
What does this mean. do this add a variable bark to function. or does this add a property to Rabbit object, even if I am not creating an object using the new operator.
Function in JavaScript is just an object, it is called Function object.
And just like any other types of object, it has its own constructor (new Function(...)), methods (apply, bind, call...) and properties (arguments, caller, name...) . See the document.
You might be familiar with creating a function like this:
function Rabbit() {
console.log('shiv');
}
Then you should know that you can also create a function like this:
var Rabbit = new Function('console.log("shiv")');
Now, you might guess it out. If you add a new property to a Function object, as long as you don't overwrite the existing one, the function is still working just fine.
do this add a variable bark to function
No, the function has it own closure, the only way to add variable to the function is to bind it to this object using Rabbit.bind(object)
do this added a property to Rabbit object
Well, since the "Rabbit object" is just an object, Yes.
what does this mean. do this add a variable bark to function. or do
this added a property to Rabbit object
do this add a variable bark to function - No
or do this added a property to Rabbit object - Yes
bark is a property of object of type Function
even if i am not creating an object using new operator
Rabit is already an object (of type Function). You are not creating an instance of this object, just that you are adding a property to it.
Related
Let us say we have a function.
function Rabbit(){
console.log("shiv");
}
Now without creating an object of this function i can assign the property of this object
Rabbit.bark = function(line) {
console.log("name is", line);
};
What does this mean. do this add a variable bark to function. or does this add a property to Rabbit object, even if I am not creating an object using the new operator.
Function in JavaScript is just an object, it is called Function object.
And just like any other types of object, it has its own constructor (new Function(...)), methods (apply, bind, call...) and properties (arguments, caller, name...) . See the document.
You might be familiar with creating a function like this:
function Rabbit() {
console.log('shiv');
}
Then you should know that you can also create a function like this:
var Rabbit = new Function('console.log("shiv")');
Now, you might guess it out. If you add a new property to a Function object, as long as you don't overwrite the existing one, the function is still working just fine.
do this add a variable bark to function
No, the function has it own closure, the only way to add variable to the function is to bind it to this object using Rabbit.bind(object)
do this added a property to Rabbit object
Well, since the "Rabbit object" is just an object, Yes.
what does this mean. do this add a variable bark to function. or do
this added a property to Rabbit object
do this add a variable bark to function - No
or do this added a property to Rabbit object - Yes
bark is a property of object of type Function
even if i am not creating an object using new operator
Rabit is already an object (of type Function). You are not creating an instance of this object, just that you are adding a property to it.
I've got a "class" that looks like this:
export function IBXMReplay() {
var onRow = function(){console.log("not right")};
....
}
Later on, it's called in a function like this:
var seqRow = function() {
onRow();
....
}
This function is essentially called by callbacks for web audio getAudio. I construct the object like this:
var replay = new IBXMReplay();
replay.onRow = function(){console.log("Right")};
However, when onRow() is called, it always prints "not right."
What am I doing wrong??? I tried creating a setter function but that didn't work either.
The problem is that the onRow function is being defined as a variable in the IBXMReplay local scope, and i'm assuming that the seqRow function is also inside IBXMReplay. Local-scope variables cannot be directly accessed nor modified from the outside.
For this to work, you'd need to make the onRow function a property of the IBXMReplay object (in JS functions are objects too):
export function IBXMReplay() {
this.onRow = function(){console.log("not right")};
....
}
Or better yet, store it in the prototype:
var IBXMReplay = function IBXMReplay() {
....
}
IBXMReplay.prototype.onRow = function(){console.log("not right")};
export IBXMReplay
Either way, you can later do:
var replay = new IBXMReplay();
replay.onRow = function(){console.log("Right")};
It should work as you expected.
Now, some explanation about that. Let's say you have 100 instances of the IBXMReplay 'class'. The differences between storing it as an object property vs. a prototype property are subtle but important:
Object property
Storing the method like this.onRow will mean there'll be 100 copies of it in memory. If you later edit it with replay.onRow = something, it'll be completely replaced for that particular instance.
Doing something like delete replay.onRow would not bring the original function back and will instead throw an 'undefined is not a function' error when executing that instance..
Prototype property
Storing the function in the object's prototype instead will mean there'll only be a single copy of onRow being referenced by all instances. When editing the instance with replay.onRow = something, the underlying prototype onRow is merely being shadowed by an object property with the same name, so any calls inside the IBXMReplay class will reference the overriding function instead.
Deleting the instance property delete replay.onRow will 'uncover' the original function.
This is how JavaScript works, and is called the prototype chain. Whenever you do foo.bar, a bar property is searched directly in the foo object, but if not found then it's searched in foo's prototype, and then the prototype's prototype, and so on, until reaching null, which has no prototype.
Let us say we have a function.
function Rabbit(){
console.log("shiv");
}
Now without creating an object of this function i can assign the property of this object
Rabbit.bark = function(line) {
console.log("name is", line);
};
What does this mean. do this add a variable bark to function. or does this add a property to Rabbit object, even if I am not creating an object using the new operator.
Function in JavaScript is just an object, it is called Function object.
And just like any other types of object, it has its own constructor (new Function(...)), methods (apply, bind, call...) and properties (arguments, caller, name...) . See the document.
You might be familiar with creating a function like this:
function Rabbit() {
console.log('shiv');
}
Then you should know that you can also create a function like this:
var Rabbit = new Function('console.log("shiv")');
Now, you might guess it out. If you add a new property to a Function object, as long as you don't overwrite the existing one, the function is still working just fine.
do this add a variable bark to function
No, the function has it own closure, the only way to add variable to the function is to bind it to this object using Rabbit.bind(object)
do this added a property to Rabbit object
Well, since the "Rabbit object" is just an object, Yes.
what does this mean. do this add a variable bark to function. or do
this added a property to Rabbit object
do this add a variable bark to function - No
or do this added a property to Rabbit object - Yes
bark is a property of object of type Function
even if i am not creating an object using new operator
Rabit is already an object (of type Function). You are not creating an instance of this object, just that you are adding a property to it.
Most of us know that JavaScript has no sense of "private" properties, but that behavior can be emulated through the use of closures:
var Car = function () {
var name = 'Tesla';
var wheelCount = 4;
this.getName = function () {
return name;
};
this.getWheelCount = function () {
return wheelCount;
};
this.setName = function (newName) {
name = newName;
};
this.setWheelCount = function (newCount) {
wheelCount = newCount;
};
};
var myCar = new Car();
console.log(myCar.name); // undefined
That all makes sense to us that know about how JavaScript closures work. However, the following will work:
myCar.name = 'Corvette';
console.log(myCar.name); // 'Corvette'
But then if you call the function from the prototype, the enclosed variable is still used
console.log(myCar.getName()); // 'Tesla'
When you call myCar.name, you're adding a new property to the object. Is it just the entire point of using this when declaring the getName (etc) functions inside the Car definition to make the differentiation between the enclosed name inside the Car declaration versus the myCar.name?
I have a feeling that I know the answer to this, but I would like to be certain. Plus, I think this would be something invaluable to other people getting an advanced grasp on how JavaScript enclosures work.
Is it just the entire point of using this when declaring the getName (etc) functions inside the Car definition to make the differentiation between the enclosed name inside the Car declaration versus the myCar.name?
Yes.
this (or myCar) is the object, on which you put the properties that you want to have it (in this case all those methods). If you want to use properties, you must use a property accessor.
var name is just a local variable in the constructor function, which is accessed by closure from the object's methods.
Or, to answer your title question:
If a variable is enclosed, and an instance sets a property with the same name, where does the property go?
The property goes on the object. It doesn't interfere at all with the variable, which is located in the scope of the Car constructor invocation.
In your example car function is a constructor function. When a constructor function is called with new operator, a new object is created and "this" gets bound to that new object. And "this" is returned from the function even if there is no return statement (unlike non-constructor functions that returns undefined if nothing is returned)
So When you called new Car() a new object got created and as "this" was bounded to this new object, the new object got 4 functions that you defined in Car function (getName, getWheelCount, setName, setWheelCount)
The name variable defined in Car function is not bounded to "this", it is bounded to Car's function scope. When car function returned "this", because of closure getName() still has access to function's name variable.
Now when you tried myCar.name, as the new object that was created does not have any variable called name, it printed undefined.
On doing myCar.name = 'Corvette', as no property named name was found in myCar,new property was created with name "name" and value "Corvette" (javascript creates a new property if it is not already existing in case of write operations, for read operations prototype chain is followed)
But surprisingly myCar.getName() still prints "Tesla" and not Corvette, because though the variable names are same they are in diffrent scope.The one that is referred by getName was part of Car function scope and is bounded to getName via Closure, but the name ("corvette") that you added belongs to new object that you created.
The purpose of "this" is to add the functions/variables defined inside constructor function to the object that you are going to create through that constructor function.
Hope it helps.
Recently I read a tutorial which says if define the function like below.
function Animal() { }
On the surface, this code seems to create a function called Animal.
But with JavaScript, the full truth is slightly more complicated. What
actually happens when this code executes is that two objects are
created. The first object, called Animal, is the constructor function
itself. The second object, called Animal.prototype, has a property
called Animal.prototype.constructor, which points to Animal. Animal
has a property which points back to its prototype, Animal.prototype.
But I have little confuse about it .What about the Function object ?What is the use for the Animal object?
And If I write code like below .
var test= new Function();
and I inspected the variable test in the Developer tool of the Chrome.
I found test is nothing to do with the Function. Can someone tell me why ? thanks.
Updated
The diagram below is the objects relationship when the code is executed, please review it.
If my understanding is wrong. please correct me. thanks.
That blog post goes into a lot of detail that's interesting but unnecessarily confusing for most people most of the time.
First, let's talk about functions; forget about prototypes for a minute. When you create a function:
function Whatever() {
// ...
}
you've created an object. That is, all functions are objects, and they're constructed via the Function built-in constructor. The symbol "Whatever" in this example will have as its value a reference to that object.
Given a reference to a function, it's possible to call it:
Whatever(); // call the function
It's possible to take that value (the reference to the function object) and assign it to another variable, or pass it as a parameter to another function, or to use it just like any other value in JavaScript.
var another = Whatever;
another(); // also calls the "Whatever" function
Constructing a function via the Function constructor explicitly is something that's rarely done, but it gives you a function that's otherwise unremarkable. (In the OP, the constructed function doesn't do anything because no code was passed to the Function constructor.)
Now, things get interesting when a function is invoked as part of a new expression.
var test = new Whatever();
By using new, a new object is instantiated and associated with the "Whatever" function. The "Whatever" function is the constructor for that new object.
Every function object, whether it's ever used as a constructor or not, has an associated "prototype" object. When a function is used as a constructor, then objects it constructs (that is, objects made in new expressions that invoke the function) are implicitly associated with that prototype object.
The prototype object becomes interesting when an object property reference expression is evaluated. Object property references look like this:
obj.name
obj[ nameExpression ]
In such an expression, the property name (either the identifier used in the . expression or the value of the expression inside [ ]) is checked against the set of properties on the object directly. If the name is not the same as one of the object's properties, then the runtime consults the prototype object associated with the constructor function used to make the object.
For most code that most people write, that relationship and some of its direct implications are the only things to worry about. You don't have to fool around with the (non-standard, at this time) "proto" property of objects unless you're putting together some sort of library or framework.
Finally, it might be instructive to look at the Object.create() function and in particular the "polyfill" shown in that documentation.