Can functions in JavaScript be called as an instance of Object? - javascript

I was recently introduced into learning JavaScript and I was literally confused when I went through the prototype concepts. Everything I read and understood got confused.
Let be get straight through..
I have two questions related to functions and Objects.
Question 1:
Can functions in JS have (key, value) pair of property in it? If so, what might me the data type of the key? Because In an Object, the key of the property can be only of the types String, Object and in some special cases Symbol.
Question 2:
How are the functions evaluated internally? Are they converted to objects?
function sample () {
// code goes here
}
and
let myFunc = new Function(,,);
Thanks

It seems your overall question is “what are functions”.
Yes, functions are objects*. That’s why they are first-class citizens. They are just like any other value. Just like other objects they can have properties (you might be familiar with f.call, f.bind, etc).
What distinguishes functions from other objects is that they have an internal [[Call]] property (internal properties cannot be accessed from user code, they are used in the specification to define internal state/behavior of objects).
The [[Call]] property contains some representation of the code in the body of the function. It’s this code that is executed when the function is called.
There are other internal properties needed for a function to work, but [[Call]] is the most important one. It is used to determine whether an object is callable or not.
Prototypes are not primarily related to functions. Prototypes are a concept applying to objects in general. They are not very complicated either: a prototype is a just an object. What makes an object a prototype is that another object has a reference to it via its internal [[Prototype]] property. Then we can say “this object is the prototype of the other object”.
Other languages work similarly. Python for example lets you make instances of classes callable by implementing the magic def __call__: method.
*: There are seven data types in JavaScript:
Boolean
Number
String
Null
Undefined
Symbol
Object
The first six are so called “primitive” data types.

You can add properties at will to a function, as in JavaScript functions are objects. In both of the syntaxes you provided for creating a function, you get a (function) object.
Example of adding properties:
function counter() {
console.log(++counter.count);
}
counter.count = 0; // create a property on the function object
// Call the function several times
counter();
counter();
counter();
As functions are objects, the same restrictions apply: property names are strings. Values can be anything. Properties are not ordered.

Answer to Question 1:
Yes, you can have key: value pair inside a function, but that function is called constructor. For example:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
In ES6: you can store similar key:value pair using constructor() function inside a class. For example:
constructor(make, modal, year) { // constructor syntactic sugar
this.make = make;
this.model = model;
this.year = year;
}
The data-type of key depends on what type of value you're storing in that key. In our example, if I store string value in this.model, data-type of model key would be string and If I store year as a number then data-type of this.year would be number.
Answer to Question 2
To understand how a function works internally, you need to understand execution context. To understand execution context, you must read this article by David. To simply put:
Every time a function is called, a new execution context is created. However, inside the JavaScript interpreter, every call to an execution context has 2 stages:
Creation Stage
[when the function is called, but before it executes
any code inside]: Create the Scope Chain. Create variables, functions
and arguments. Determine the value of "this".
Activation / Code
Execution Stage: Assign values, references to functions and interpret
/ execute code.

My best advice would be to jump into Chrome console and play there. Really good way to fit bricks in their places.
Can functions in JS have (key, value) pair of property in it? If so,
what might me the data type of the key? Because In an Object, the key
of the property can be only of the types String, Object and in some
special cases Symbol.
Sure they can. But you misunderstood something about Object as a key. You can do this:
var obj = {};
var key = {};
obj[key] = "Smthg";
But that would work just because key would be stringified. So obj[key] would be converted into obj["[object Object]"]. Test it out:
var obj = {};
var key = {};
obj[key] = "key1";
obj["[object Object]"] = 'key2';
console.log(obj[key]);
As you see, no matter how many objects you will use as a key - they will override each other.
How are the functions evaluated internally? Are they converted to
objects?
JS is OOP language - everything is an object (except some primitives etc.). So that means there are many different objects. And they inherit something from each other, otherwise there would be a one GIANT object with all those properties bounded and endless waiting time to load your first "Hello World" application.
My probably best tool to learn JS, after taking some readings is console.dir() method (or just dir(someVar) if in console mode).
Create object - var f = new Function() and dir(f) to see what is it and what is its prototype etc.

Now its a good question , which can confuse many. First thing there is the concept of constructor and prototype in javascript
So
function A() {
console.log("A")
}
if you console.log(typeof(A)) // "function"
now A has also a protoype
console.log("Aprototype", A.prototype)
that will be an object
That native object has a property proto
console.log(A.prototype.__proto__)
This will be parent prototype. from which the current prototype is inheriting. This parent prototype will also have a constructor, That is your Function constructor
console.log("parentConstructor", A.prototype.__proto__.constructor)
Now this parent Protype has also one more proto, which is linked to Object function constructor
console.log("parent parent __proto__", A.prototype.__proto__.__proto__)
and its constructor is your Object constructor function.
Thats why you are able to get new object
var t = new Object()
Look how we have called it like constructor.
Thats how prototypical javascript is :)

Related

At what point does a function object have properties?

Functions being first class objects, it seems their local data at some point must have properties, but I'm confused on when/how this happens.
Take for example:
var output = function(x){
var s = "string";
delete s;
return s + " " + x;
};
console.log(output("bean"));
outputs string bean. I'm not sure if I expected it to delete s or not I was just messing around, because I thought var declared globally become a property of the window object.
I know delete doesn't work on local variables, and it only works on object properties. And because Functions are objects, I'm wondering at what point does local data in a function become a "property"
I'm wondering at what point does local data in a function become a "property"
It doesn't. You're confusing a function invocation with ordinary object-like interaction with the function.
Like all objects, functions can have arbitrary key-value properties associated with them eg:
var fn = function(x){
// do something
// not important
};
fn.foo = 'foo';
console.log(fn.foo);
Unless you explicitly assign a property to the function like this, the function won't have properties other than the usual ones that a function has (like .prototype).
Still, assigning such arbitrary properties to a function is pretty weird, and probably shouldn't be done in most cases.
Other properties that functions often have are .name (named function name), .length (refers to the number of arguments the function takes).
This is in contrast to non-object primitives, which cannot have key-value pairs assigned to them:
'use strict';
const someStr = 'foo';
someStr.bar = 'bar';
(though, when you try to reference a property on a primitive, the interpreter will turn it into an object by wrapping it in the appropriate prototype first, so that prototypal inheritance works with it)

Purpose of this Javascript prototype snippet

Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)

If there is no distinction between classes and objects why doesn't this code work?

I was always taught that in Javascript there is no distinction between objects and classes. Then can someone explain why this code generate error:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
firstObj.sayHi();
Whereas this one works:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
new firstObj().sayHi();
What's the difference? Why isn't the first one working?
The key issue here is that your firstObj variable is a Function object, not a firstObj object. This is a subtle distinction, but the type of object determines which prototype it inherits.
The prototype is like a template that is applied to newly created objects of a particular type. You must create a firstObj object (usually with new which invokes the constructor and assigns a prototype) in order to have that template applied to it. In the first example, your firstObj variable is a Function object, not a firstObj object so it has the prototype of a Function not of anything else..
In your second example, you actually create a firstObj object so it inherits the prototype for that type of object.
If you want the method applied in your first example so it works on the function object you've already created, just put the method directly on your already existing function object, not on the prototype.
There is no difference in the language between objects and classes1. However, there is a big difference between one kind of object and another. In the first case:
firstObj.sayHi();
you are trying to access the sayHi property of firstObj, which is a Function object that does not have such a property. (You could, however, do firstObj.prototype.sayHi().)
In the second case:
new firstObj().sayHi();
you are first invoking the new operator on the firstObj object, which evaluates to a new object. That new object has firstObj as it's constructor property and a prototype equal to the prototype property of firstObj. You are then accessing the sayHi property of that returned object, which succeeds because sayHi is in the prototype chain for that object.
1 Technically, JavaScript doesn't have classes2 (in the traditional sense), just constructor functions that are usually called "classes".
2 However, class is a future reserved word.
when you write this:
var firstObj = function() {};
you only define a constructor function, thus you need to use the key word new for the new objects created with this constructor function.
A function is just a function until new is issued. At that point, a Function Object is created based on the prototype for the function. That is why you will not see the sayHi method present in the first version.
Also, firstObj is a function, and not an object, so you need to invoke it to actually have anything happen. firstObj will not actually invoke the function, you must use firstObj().
Further, there are ways to have the prototype used without explicitly requiring the new keyword. This is done in a number of popular frameworks (such as jQuery). It is done by checking to see if new was used, and if it was not, then it news one up for you on the spot:
jsFiddle Demo
var firstObj = function() {
if( !(this instanceof firstObj) ){
return new firstObj();
}
};
firstObj.prototype.sayHi = function() {
alert("hi");
};
firstObj().sayHi();

JavaScript function called object with lower-case "o"

I just watched an introductory JavaScript lecture from Douglas Crockford, in which he mentions a function called object that should be used to create a new object linked to an object as its parameter. I would guess what he means by that is that if I say
var objB = object(objA);
The objB's internal [[prototype]] reference is set to objA, although he didn't explicitly formulate it like that.
On the other hand, I have read his book, in which he doesn't mention such a function at all and instead presents his own way of creating an object from a prototype, defining following function :
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
}
Essentially taking advantage of the behavior of the new operator that sets the internal [[prototype]] link of the newly created object to whatever the constructor function's prototype property points to.
My question is why would he omit a built-in function and invent his own way to do the same thing. Is the former call to object function really equivalent to
var objB = Object.create(objA);
Or is there some slight difference ?
The two functions are one and the same, and neither are built in to JavaScript. See Crockford's article describing why he switched between the different naming conventions.
Edit from the future: I saw this old answer and wanted to point out that Object.create() is indeed a native (and very important) ES5 method.
There is no difference. And here is "simplified" explanation:
The thing is, everything in javascript is an object and inherits from Object.
Also you can look at "function" as directive which defines new type of object, actually constructor of object if you are using new keyword. If you don't use new keyword and call function like in example below
function doSomething(){
alert("works");
}
javascript engine will create object doSomething which will contain prototype property, this prototype is defined type of object doSomething and it contains constructor which is created by javascript developer with code above. For bult in functions or prototypes, constructors have native code

How does an object reference itself in Javascript?

I was experimenting with inheritance in javascript, and wrote those two functions:
Object.prototype.inherits=function(obj){this.prototype=new obj;}
Object.prototype.pass=function(obj){obj.prototype=new this;}
This code works very well:
Dog.inherits(Animal);
But the following fails:
Animal.pass(Dog);
As I understand it, my pass functions doesn't work, because "this" isn't a reference to the object instance itself? If that's the case, how can I reference the object from within itself?
Thanks in advance!
Well, actually the two are doing exactly the same:
Dog.prototype = new Animal;
The this value inside the methods will refer to the base object where the reference was invoked, in the case of:
Dog.inherits(Animal);
The this value will refer to the Dog constructor function, and the obj argument will be the Animal function.
When you call:
Animal.pass(Dog);
The this value will refer to the Animal function, doing at the end exactly the same thing as the inherits method, but the other way around.
I would recommend you to not extend the Object.prototype object, because it can cause you a lot of problems, for example those two properties will be enumerated in any for-in loop, e.g.:
for (var prop in {}) { // <-- an empty object!
alert(prop); // will alert 'inherits' and 'pass'
}
All objects inherit from Object.prototype, and it seems that you intend to use those methods only on Function objects, it would be safer to extend the Function.prototype object, or implement the methods as functions that take two parameters.
Works for me, with test code like:
function Animal() {}
Animal.prototype.isanimal= 1;
function Dog() {}
Animal.pass(Dog);
Dog.prototype.isdog= 2;
alert(new Dog().isanimal); // 1
alert(new Dog().isdog); // 2
However, bear in mind that new this or new obj will call the function this/obj, creating a new full instance. If you have constructor code in that function that expects to receive some arguments, or sets up instance state, you can end up with problems. To create a new this without calling this as a function you can use a different constructor that does nothing:
function nonconstructor() {}
nonconstructor.prototype= this.prototype;
obj.prototype= new nonconstructor();
Also, you should avoid prototyping onto Object. This will cause trouble for code using Object as a general-purpose lookup map. As you only seem to be working with constructor-functions, prototyping onto Function should meet your needs and is much safer.

Categories

Resources