Difference between Object.method(o) and o.method() [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?
I noticed that all the methods of a particular object can be called from the actual object instance, i.e., object.method(); or by passing the object to Object.method() as an argument. For example:
var a = ['one', 2, 3, 'four'];
a.reverse();
// OR
Array.reverse(a);
I seemed to get the same behaviour. I was wondering what the difference was and when one would be used over the other?

Object.method(o) looks on the Object object (Object is a real object in JavaScript) for a property called method and tries to call it passing in the variable o. During the call, this will be Object.
o.method() looks on the object referenced by the variable o for a property called method and tries to call it, not passing anything in. During the call, this will be o.
As you can see, they do quite different things.
I noticed that all the methods of a particular object can be called from the actual object instance...or by passing the object to Object.method() as an argument.
No, they cannot. Your example Array.reverse(a) fails on a standard implementation of Array because Array doesn't have a property called reverse and so it can't be called as a function. Edit: You note in the comments that it works in Firefox's scratchpad, and I just verified that. That means Firefox's SpiderMonkey JavaScript engine is applying a non-standard extension to Array which provides a static implementation of reverse. That's specific to Firefox's Array, not general to all objects. (If you make your own Foo, for instance, its prototype functions don't magically get added to Foo as well.)
The standard way to make the near-equivalent to a.reverse() would be via the prototype, like this:
Array.prototype.reverse.call(a);
That does work in standard engines. So let's look at what it does:
It gets the prototype property from Array.
It gets the reverse property from the object it got in #1.
It calls the function that property referenced using the Function#call feature of JavaScript function objects to make this be the argument you pass into call during the course of the function call.
When you create an array, the object gets an underlying prototype. That prototype is the object referenced by Array.prototype when the new array is created. So a has a reverse property because its underlying prototype has a reverse property.
Doing a.reverse() does this:
Gets the reverse property from the a object. Since (normally) a won't have its own property called reverse, standard JavaScript property lookup looks to a's underlying prototype. It finds the property there and uses its value.
Calls that function such that this is a within the call.
As you can see, the end result is the same provided that the underlying prototype of a and Array.prototype still refer to the same object. (It's possible for them not to, although in the case of Array or any other built-in, if someone replaced [as opposed to augmenting] Array.prototype, that would be a Bad Thing(tm).)

Related

Javascript Manual: `Array.prototype.includes()` vs. `Array.includes()`

Incoming "noob" question:
Javascript has an includes method on arrays.
It looks like:
Array.includes()
But when I go to the Javascript Manual to understand this method, the heading on that page (for an appropriate technical reason, I realize) is:
Array.prototype.includes()
Similar things in the Javascript Manual have caused me to not like the manual at all (and alas, I rely on W3Schools more than the manual).
However, I really really want to learn to interpret the manual.
So, my question is: what's the significance of including the word .prototype in Array.prototype.includes() in the documentation, when the actual usage looks like: Array.includes()?
(Also, if anyone has suggestions on how I can improve my comprehension of the official Javascript Manual, I'd appreciate suggestions.)
So, my question is: what's the significance of including the word .prototype in Array.prototype.includes() in the documentation, when the actual usage looks like: Array.includes()?
The significance is that actual usage doesn't look like Array.includes():
Array.includes();
That will throw a TypeError: Array.includes is not a function because Array.includes doesn't exist. Accessing a non-existing property evaluates to undefined, so Array.includes evaluates to undefined and thus Array.includes() is trying to call undefined as if were a function.
You can see that in action here:
console.log(Array.includes);
undefined();
The includes() method is defined on the prototype of the Array global object so that you can call it on instances of Array:
[].includes();
You can see that [].includes is a function:
console.log([].includes);
Compare this to Array.from which is defined on the Array constructor, not on the Array prototype:
console.log(Array.from);
You can use it like this:
console.log(Array.from({ length: 10 }, (_, num) => num << 2));
If the documentation said Array.includes() you would literally type it like this (example):
Array.includes(1);
Instead it says Array.prototype.includes() which means it isn't called on the Array type itself, but on an instance of it. So in this case you would write:
const numbers = [1, 2, 3];
numbers.includes(1);
JavaScript is often described as prototype-based language, prototypes is simply how inheritance works in JavaScript.
What does prototype means ?
Both of us agree that almost everything in JavaScript is an object (I said "Almost" because primitives are not considered objects) cool?
Okay, now every Object in JS has an internal property called [[Prototype]] and by internal I mean that you can't access it directly the same way you access a JS object's property.
If we want to know the prototype of an object that we have created we either pass the instance of our object to Object.getPrototypeOf or through the __proto__ property of our object
For example:
let myArray = [1,2,3,4];
console.log(myArray.__proto__)
// Expected output: Array []
If you expand the resulting object you get from the little code snippet above you will find the includes method you were asking about and all of the methods available on any array you create in a JS code!
That's because myArray and all arrays in JavaScript are said to share the properties and methods defined on Array.prototype!
Now, if you look again at the methods of the resulting object which you have from the code snippet above you will notice a method called constructor, defined on the Array.prototype just like includes and the other methods
That's the function invoked when you create an instance of the JavaScript Array object!
What do we mean by the JavaScript Array object?
It's a global JavaScript object that is used in the construction of arrays, it's the Array in Array.prototype.includes() (you may call it a class for convenience buuuuut classes did not exist practically until the release of ES6...before then there was no such thing as class in JS)
So to keep it simple and wrap it up think of Array as the global object that alll JS arrays are instances of, and think of Array.proto as it's prototype which wraps the properties and methods that all of its instances share!
And regarding the documentation, being able to read the documentation and have a considerable understanding of what you read is actually something good so I believe you're just fine !

Why do some array methods rely on the global Array object?

I'm going through the MDN docs on arrays and when we want to test whether or not an object is an array we use isArray(). However, it's usage is very different to most of the other methods. When you use the regular syntax an error pops up:
console.log([1,2,3].isArray()); // TypeError: [1, 2, 3].isArray is not a function
Whereas this does work:
console.log(Array.isArray([1,2,3]))
I don't understand why isArray() (and a couple of other methods) rely upon some global object rather than just being accessible via the object in question. Why do some methods require the global array object?
rather than just being accessible via the object in question.
Because the whole purpose of Array.isArray is to be called on unknown objects. You don't know whether it's an array, you wouldn't know whether the method was accessible on it. The static method even works with values like null, which would inevitably throw an exception when you tried to invoke a method on them.
Digression:
isArray being callable as an instance method can work. In languages where everything is an object, like Smalltalk, Ruby or Io, even things like nil can have a isNil method. This approach has other problems of course, as with dynamic method dispatch every arbitrary object could overwrite the method and claim to be an array - on the other hand, that's exactly what we want for duck typing.
We could even simulate this in JS using Object.prototype.isArray = () => false; and Array.prototype.isArray = () => true;. Apart from failing on null and undefined, it still wouldn't work with objects that don't inherit from (our realm's) Object.prototype. And JavaScript "properties" that mix data fields and methods don't help either (consider the object parsed from the JSON string {"isArray":"maybe"}). We would always have to expect an exception from either .isArray not being a function, or from it being overwritten with a method that throws.
If we want to go for duck typing in JS, checking whether an object has an integer .length property is usually the way to go. Or more advanced, trying to follow the symbol-based iteration protocol. (That's what Array.from uses, for example).
But since arrays are a bit special in JS (with their magic .length property), we want a built-in reliable way to detect them, and that's what Array.isArray does.
Regarding other static Array methods: Array.of is pretty obvious, it's a factory function (like a constructor) and it can't be an instance method because there is no instance to work with in the first place. For Array.from the situation is a bit more like with isArray, a duck-typing Object.prototype.toArray approach could have worked as well but was dismissed for practical and design reasons.
See also Why were ES5 Object methods not added to Object.prototype?, Why use Object.prototype.hasOwnProperty.call(myObj, prop) instead of myObj.hasOwnProperty(prop)? and Why is it Object.defineProperty() rather than this.defineProperty() (for objects)? for similar discussions.
.isArray() is a static method, it exists on the Array "class" but not on each particular instance. Static methods are called like this: Array.isArray(). Object.create() is another example.
Methods like .map or .slice are not static, so they exist on each instance of the Array "class".
Array (denoted with a captial "A") indicates the JavaScript native Array object. [...] represents an instance of an array. As with many languages, some properties/methods are static. That is, they don't exist on instances only the type. This is often done when the value of the property or behavior of the method doesn't vary from instance to instance, so there's no need for it to be "instance-specific". Figuring out if something is an array, doesn't change from instance to instance (and frankly, doesn't make a lot of sense to ask an array instance if it is an instance of an Array).

why typeof(Function.prototype) is function

I am aware of the fact that Prototypes are object literal. So methods and properties can be defined on them. Function.prototype has some method like apply, call, bind, toString etc. So I thought a function's prototype should be a object literal. But I ran following code and encountered that Function.prototype is of type function !
console.log(typeof(Function.prototype)); // function
How come it is not a object literal itself ?
From the specification:
The Function prototype object is the intrinsic object %FunctionPrototype%. The Function prototype object is itself a built-in function object. When invoked, it accepts any arguments and returns undefined. It does not have a [[Construct]] internal method so it is not a constructor.
NOTE
The Function prototype object is specified to be a function object to ensure compatibility with ECMAScript code that was created prior to the ECMAScript 2015 specification.
(my emphasis)
If we go to the ES5 spec, it says:
The Function prototype object is itself a Function object (its [[Class]] is "Function") that, when invoked, accepts any arguments and returns undefined.
...without offering any explanation for why that would be the case. That language is essentially unchanged in ES1, ES2, ES3, and ES5. I think the original idea was basically that that was what gave it its function-ness, although typeof (even in ES1) didn't look at the internal [[Class]], it looked at whether the thing implemented [[Call]] (as it still does). When something goes back all the way to ES1, one frequently has to just invoke the "because Eich did the first JavaScript in 10 days and yeah, weird stuff happens when you do that" argument. :-)
Side note: By "object literal" I take it you mean "plain object." (An "object literal" — what the specifiation calls an object initializer — is just a way to write an object in source code. There are other ways to create plain objects.)
An object literal is some JavaScript syntax for creating objects. It isn't a data type.
Functions are just a specific type of object in JavaScript. Anywhere you can have an object, you can have a function.
Let's say you have declared an array,
let arr = [ 1 , 2 ];
So, internally it will be created as
let arr = new Array ( 1, 2 );
This is the function constructor.
Have you ever thought about how the array got all functions like concate, map, filter, reduce etc.?
Internally when we create an instance from a function constructor, the prototype property of a function will be set to the prototype property of that newly created instance. Hense, this concate, map, filter, reduce get automatically associated with that function constructor. So that's how we can use that array properties by arr.map, arr.concate.
Actually the prototype property of a function is visible but the prototype property of an instance which is created by a function constructor is hidden. If you want to check then you can check it by obj_name.proto. It's a pointer towards that prototype property.
Now, you can see that the array "arr" is not the array internally. It's an instance of a function constructor. That's why if you check the type of the array, you will get the answer as object and also if you check the typeof(Array), you will get the answer as Function.
If you find it useful then please like it on
https://www.linkedin.com/posts/sh-jay_javascript-array-prototype-activity-6951547190049677312-Dqbn?utm_source=linkedin_share&utm_medium=member_desktop_web
Well, I don't think you mean object literal, as alluded to by other answers and comments.
alert(Function.prototype instanceof Object) // true
alert(Function.prototype instanceof Function) // true
alert(typeof Function.prototype) // function
It is an object. It's also a function. Also, all functions are objects. They're all following the rules just fine.
alert((function(){}) instanceof Object) // true
alert((function(){}) instanceof Function) // true
alert(typeof (function(){})) // function
One big happy we-all-derive-from-Object family. Why should the prototype of Function not be a function?
Now if you wanna get weird... let's get weird.
var notAFn = Object.create(Function.prototype);
alert(notAFn instanceof Function); // true
alert(typeof notAFn); // object
And no, you can't call notAFn(). Not until they add a call Symbol for that. :)
Oh hey, feel free to tell me why this isn't a good answer. I'll try to improve it.

Example of Properties vs. Methods in JS

I found a great description of the semantic difference between Properties and Methods (paraphrased, via http://www.webdeveloper.com/forum/showthread.php?133712-Properties-Vs.-Methods):
Properties are like nouns. They have a value or state.
Methods are like verbs. They perform actions.
A property can't perform an action and the only value that a method has is the one that is returned after it finishes performing the action.
e.g.
Property: door; Possible Values: open, closed
Method: openDoor; Action: to change the value of the door property to "open"
Creating an example: I understand this in theory but I can't come up with an example. Would it be possible to show me how the door/openDoor would look in actual Javascript code?
Really, you need to back up and read some of the links posted above. But as a quick example:
var house = {} ;
house.isDoorOpen = false ;
house.openDoor = function(){
house.isDoorOpen = true ;
}
Here house is the object. It has a property: house.isDoorOpen. Here, it is more like an adjective. Either the door is open (true) or closed (false). As it sounds, it describes a property of the house.
Also, it has a method openDoor (which is used like this: house.openDoor() ). That's something that it can do. In this case, the action openDoor affects the isDoorOpen property, making it true.
Let's look at how the javascript spec ECMA-262 describes the term property
http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.26
4.3.26 property
association between a name and a value that is a part of an object
NOTE Depending upon the form of the property the value may be
represented either directly as a data value (a primitive value, an
object, or a function object) or indirectly by a pair of accessor
functions.
4.3.27 method
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
Also
Javascript's definition of attribute is different from Java's
4.3.29 attribute
internal value that defines some characteristic of a property
for in, loops through an object's enumerable properties, and that includes its functions
http://eloquentjavascript.net/1st_edition/chapter8.html
"A function is called as a method when it is looked up as a property,
and immediately called, as in object.method()."
There does seem to be a more standard definition of property..
https://en.wikipedia.org/wiki/Property_(programming)#JavaScript
"A property, in some object-oriented programming languages, is a
special sort of class member, intermediate between a field (or data
member) and a method. .... Some object-oriented languages, such as
Java, don't support properties, and require the programmer to define a
pair of accessor and mutator methods instead."
In that more standard, non-javascript definition of property
C# has properties, and Java doesn't have properties
Object in JavaScript is just key-value pairs stored in a Hash. The difference between b/w property and method is that - property is a value stored in the hash key, whereas method is a function stored in the hash key.

Every Object is a function and every function is Object - Which is Correct?

I was reading this link JavaScript_syntax
This seems to be cyclic - that every function is an Object and every Object itself is a function. Which is the atomic one? Can someone explain in a better way?
Anything that is not a primitive type (undefined, null, number, string, boolean) is an object (or an instance) in JavaScript. That means function inherits from object.
Object instances can contain more instances which can be functions. That's what we call a "method" (since it has an automatic this variable).
Since you can't "call" every Object instance, not every object is a function.
I think this concept is often misunderstood.
A utility to visualize JS types relationship http://jstype.herokuapp.com/#/home
Javascript Data Types
Primitive types - numbers, strings, booleans, null and undefined.
All non-primitive types are object:
var foo = { };
var foo = [1, 2, 3];
var foo = function abc() { return "hello world"; };
var foo = new Number(30);
var foo = new String("Hello World");
var foo = new Boolean(true);
var foo = new RegExp(/[foo]+/);
// All 'foo` are object.
All primitive types have a corresponding Constructor Function wiz. Array, Number, String, Boolean, RegExp. As all functions are objects, they are objects too. So we can call them Constructor Function Objects.
Most of the non-primitive type has prototype property where all inherited stuff lives. Math doesn't have prototype.
All objects inherit from Object.prototype which inherits from null.
object <- Object.prototype <- null
All native functions inherit from Function.prototype which inherits from Object.prototype.
function <- Function.prototype <- Object.prototype <- null
Arrays inherit from Array.prototype which inherits from Object.prototype.
array <- Array.prototype <- Object.prototype <- null
Must read MDN: Inheritance and prototype chain
To get confused Stackoverflow: prototype in JavaScript
Stack Overflow: Function prototype explained
Every function is an object. Objects can contain functions (methods) but an object is not necessary a function.
Also Function is always a property of an object.
This mean that all functions in JavaScript is always bound to an object. If you don't specify an object to bind a function to it's bound to the window object (Also called global functions)
..fredrik
It would be better to say that in JavaScript everything can be treated as an object, that includes primitive types as well as functions types; what the JavaScript interpreter does is that it automatically promotes your primitives and functions to their object wrapper types when you interact with them.
There is also a Function object, an a number of equivalent Wrappers for the other primitives in JavaScript, that means that you can even call methods on functions instances, like:
myFunction(someArg).call(this)
That being said, not every object is in fact a function.
As others have said, functions are objects that can be passed around by reference like other javascript objects. Not all objects are functions, only those that are declared as such.
You will often see methods declared like so:
var myFunc = function(foo, bar) {
...
};
This is to reinforce the fact that the method is a function object and as such it is a property of the object where it is defined, just like any other variable you might define with var.
This is the foundation of the most important feature in javascript, closure.
Every function is an Object.
I'm not an javascript expert, but I cannot see how every Object is a function. (I can see how every object could be a function, but that's different)
Quoting from Working with Objects - MDN Docs
section Using Object Initializers last paragraph:
"In JavaScript 1.1 and earlier, you cannot use object initializers. You can create objects only using their constructor functions or using a function supplied by some other object for that purpose. See Using a Constructor Function."
meant that all objects WERE functions! Specifically, upon evaluation, instances or instantiations of functions.
Literally, ALL objects of that vintage were created syntactically with constructs like:
"newobj = new constructFunctor(arg1,arg2){this.prop1=arg1 /* etc */}(val1,val2)"
AND in the string that makes the object "newobj" there is the word "constructFunctor", the name of a function. The statement is intentionally quoted to impress the fact that it must be eval()'d to be executed. Prior to execution "newobj" is "equated to" a function because the statement MUST have one and "is" one by virtue of "constructFunctor"'s literal existence to define newobj's value upon execution. The quoting, and not, is very intentional in order to elucidate this abstraction. However, because JavaScript DOES have an eval function, this abstraction is in fact intentionally incorporated into the JavaScript language.
The legacy of this is still fundamental to JavaScript, though some syntactic short cuts have been added as "object initializers" using the shorthand notation like: "no={}". That the paragraph quoted above is still resident in the current documentation IS significant for the very reasons noted.
Furthermore, JavaScript also exemplifies the fundamental paradigms of Functional Programming. This defines everything as a function using the abstractions of Recursive Function Theory and the Lambda Calculus! For instance 0(), 1(), 2(), ... are the constant nonary functions better known as 0,1,2,3, ...
JavaScript is completely consistent with a Functional Programming Style approach rather than the common OOPS (pun intended Object Oriented Programming Style).
Just for supplementary to Aaron Digulla's answer.
In javascript not every object is a function. But Object,Array,String and many other built-in objects are functions that used with new operator to create object. I think this is what confused most people.
javascript everything is a hashtable. Ryan Dahl said this in one of his talks. thats what json is also; a hashtable definition. thats why u can access an object using array notation or object property notation. the value of the hashtable can be a function as well which is a hashtable. or rather an associative array
type Object in the console u get { [native code] } which is a hashtable
Object is an abstract data given to a class and that class is assigned to an object. Object can have properties and properties can hold values and functions.
Or simply for the sake of making it easy to understand you can say that anything that is not primitive data type (number,string, boolean, unll & undefined) can be classified as an object.
the selected answer by Aaron Digulla's is not 100% correct because it says,
Anything that is not a primitive type (undefined, null, number,
string, boolean) is an object.
but a string is an object. That is why you can do things like:
myString="Hello World";
x = myString.length;
newString = myString.toUpperCase();
link = myString.link("http://www.hello-world.com/");
And many other methods can be applied to the string object.
You could also initialize the string like:
myString = new String("Hello, World!");
But because a string is also a datatype it is much easier to initialize it by just applying a value.
Not necessarily an answer to the question ... just a clarification/correction of Aaron Digulla's answer.
The selected answer is wrong. In JavaScript everything is a function, except primitive types. Object itself is a function which is called function Object(). Use for example the following code:
<script>
alert(Object);
</script>

Categories

Resources