I am trying to really understand the javascript language. I am learning the differences between functions and methods.
This answer explains that methods are functions attached to objects: Difference between a method and a function
But this article from MDN says that
A value of property can be a function, which is then known as the
object's method.
The sentence from MDN implies that JS objects have single methods. Is that correct? In other words: can javascript objects have multiple methods? Or is there a javascript concept roughly akin to "The Object's Method."
An object can have multiple attributes. Those attributes can contain functions. Functions are also objects, so they in turn also can have multiple attributes and so on.
Javascript objects can have multiple methods, I think whoever wrote that article just worded it incorrectly, or a little ambiguously.
Javascript objects can certainly have multiple methods.
I find the quote less confusing if we preserve the original italics:
A value of property can be a function, which is then known as the object's method.
The "the" goes with "object", not "method".
It can have multiple methods. But it can only have one value at a time. But you could even have multiple methods that each return the value...
JS objects can have multiple methods like
window.alert("");
window.confirm("");
window.prompt("");
Related
In a recent JavaScript interview I was asked about overloading vs overriding. I know this is a concept in Java. But is there something similar in JavaScript, and if so what would be code examples? My understanding is that overloading isn't common in javascript. Why would you need to use "overloading" in JS?
OverRiding is a bit clearer to me - an example of over riding would be in subclassing where you are inheriting from a super class but over riding some methods/properties to create unique ones for a sub class.
JavaScript does not support overloading.
JavaScript supports overriding, so if you define two functions with the same name, the last one defined will override the previously defined version and every time a call will be made to the function, the last defined one will get executed.
more read here http://blog.mastykarz.nl/overloading-functions-javascript/
There's a nice example of 'faking' JavaScript function overloading here: https://stackoverflow.com/a/457589/2754135
You basically use a parameter in your function that takes an object, that object contains any number of parameters you want.
It's not actually overloading obviously, cause that's not possible in JavaScript.
there is no need for the traditional concept of overload in javascript, because of its dynamic nature. In the more traditional programming languages, as Java, you can define a method multiple times with different signatures and the language will correctly use the method you want to call just using the signature: thats called overload of methods. On the other hand override is the possibility to redefine a method of the parent class in the child class.
To do overload in javascript it is common practice to use last parameter that is called options. For example
function yourFunction(firstParam, secondParam, options) {};
the options is just a javascript object that have props you want to pass. Then you can use the so called "options" pattern to check for props.
To do override it is more difficult in pure javascript because of the prototypal nature of the language: when you "extend" a base object with a new one, you can use .call() function of the constructor object passing this to decorate the newly created object with the parent props.
While JavaScript does not support overloading in a traditional sense,
More than the required arguments may be passed at any time to a JavaScript method, and accessed through the arguments variable. This is functionally similar.
I understand that call allows you to pass in an object in place of the 'this' that the method was invoked upon.
"abc".charAt.call("defgh",1);
"e"
But suppose I want the length property to be applied to that object
I can't say
"abc".length.call("defgh");
i'll get an error
Can I do it for a property e.g. length?
Added [since this addition, the 3 answers I see to this question are all good]
It appears some people have thought I was questioning how to invoke a property (which makes no sense). I am not.
And some have thought that I was suggesting that "z".charAt("asdf",0) is better than "asdf".chatAt(0) I am not.
What I am saying is that you can use call on a method to cause it to execute/evaluate on a different object. I could give a more useful example if you really need to see a more useful example.
[1].forEach.call("asdf",function(x){console.log(x+x);});
or
Array.prototype.forEach.call("asdf",function(x){console.log(x+x);});
So forEach can be more concise than a For loop.
So there, even though initially the example I gave for call was not useful, lo and behold, a useful example can exist.
So too, that may be the case with a property
I may want to apply a different object, for a property e.g. 'length' to evaluate on. That should not be impossible in theory(as one answerer suggested before deleting his answer). I don't have a particular use I can come up with that would be beneficial for evaluating a property on a different object, but it should not be impossible.
And just because I don't have a use for it, doesn't mean it should be thrown away. Remember that prior to giving a good usage for call on a method, some said it's pointless, then I gave potentially be a use for it. And that's no argument for it being impossible in theory/principle.
There is no equivalent way to take the functionality behind the .length property and apply it to a different object. Javascript does not have that feature.
Part of the reason is because a property can be just a static value stuck in a property on an object, so there's meaning to evaluate the "ttt".length property on another object. You can access the .length property on another object, but there's no semantic meaning to using the "ttt" object's .length property on another object. The only semantic thing you have is a name. You can use that name on another object as in obj2["length"] or obj2.length, but all you've borrowed from the "ttt" object is the name of the property. It's different with functions that are methods on objects. They are executable code that is passed a this value as context. .call() allows you to take any function (whether a method or not) and specify the value of this when it is executed by using .call(). That's why you can take a method on one object and call it in the context of another object. But, a plain (non-function) property just doesn't have that capability. There's nothing to "execute" in a different context. The property just has a name and a value. You can use the name on any other object, but there's no code you can execute in a different context for that property.
Also, keep in mind once you've retrieved "ttt".length, all you have at that point is a number. That number has no context about where it came from so there isn't really any way to apply the logic that generated that number to some other object.
As for .call(), it is a method of a Function object. So, you can only use it with functions. That's why it works fine with the .charAt() method because that's a function.
But the .length property is not a function (it returns a number) so it does not have a .call() method. That's why what you're trying does not work.
Because .length is not a function, you cannot take the functionality behind it and arbitrarily apply it to another object the way you tried to do with .charAt(). That simply isn't supported with non-functions.
You can, of course, just use the .length property that is already on your other string as in:
console.log("defgh".length);
If you can describe what you're really trying to accomplish, we can probably offer a different way to do it that is supported, but your current description of what you're trying to do does not really seem logical so it's hard to figure out what the actual problem is you're trying to solve.
FYI, there's really no reason to have done this either:
"abc".charAt.call("defgh",1);
You might as well just do the much more direct scheme of calling a method on the desired object:
"defgh".charAt(1); // "e"
It is technically impossible in JS since after the "abc".length expression is evaluated the property name is lost (and only the value is carried over next), hence you cannot re-apply it to the another context.
So even if you extended the primitive type wrapper prototypes - you still would not be able to extract something more but the value.
So it just does not fit into the current language specification.
The purpose of call and apply is to set the this object within a function call. They are necessary for calling functions as methods of objects that don't have that method. However, the caveat is that the object supplied as this can be used by the function.
Applying that principle to properties means trying to read a property of an object that doesn't have it, using the algorithm from some other object that does.
If you consider the length property that many objects have, the algorithm for determining it is very different for each type of object:
String: number of characters
Number: undefined
Function (built–in): as defined in ECMA-262
Function (native, not built–in): number of arguments
Array: whatever has been set, but always at least 1 greater than highest index if there is one
and so on. So which should be the generic version returned of there was an equivalent of call for properties? So There is a very large matrix of property algorithms and objects to apply them to.
However don't despair! If you wish to use, say, the String version of length for some object, then convert it to a string and get its length. E.g. the string version of length for an array might be:
someArray.join('').length;
So you can define the algorithm for such properties any way you like. ;-)
PS. getters allow you to do this on a per object basis, but they can't be shared.
When I define an object I can reach all its properties by using the dot character and the same applies to built-in functions like String, Array, Math, etc.
But I cannot loop through them by using for(# in # for example. It says String is native code but still I can reach all its members albeit I cannot iterate through them.
I know window is iterable but their 'sub-functions' appear to be not.
Why is that? Is there a chance to call the properties without explicitly typing their names in? Can I list all its members somehow?
I am aware of that It does not look useful and no one would need it in production. I am asking it because I could not do it and I hope someone can give me some help.
You can get all names only of own(!!!) properties
Object.getOwnPropertyNames(YOUR_OBJECT)
It means, this method doesn't enumerate inherited properties. And if you want to enumerate inherited properties you can use YOUR_OBJECT.__proto__, but it works only in Mozilla
I noticed there is _.bind and _.bindAll in Underscore. I was wondering when do you use one over the other? What if you have multiple this that you need to bind, which one would you use?
Well they do similar but quite different things. The _.bind() function is for binding a single function to an object, while _.bindAll() is about binding some or all of the function-valued properties of an object to the object.
Thus _.bind() is useful when you've got any situation that requires a function be invoked with a fixed receiver, and _.bindAll() is useful when you're working with more "objecty" code. That is the case when you've got objects with properties that are functions, and these functions expect (require) that they be invoked with the object as the receiver so that they can access other functions.
The examples in the Underscore documentation explain further.
Note that modern JavaScript runtime environments have a .bind() method on the Function prototype, which (seems to me) should be preferred over _.bind().
edit — As to your questions about having to create bound functions for multiple objects, the answer is that neither of _.bind() and _.bindAll() addresses that. You simply have to iterate somehow and collect the bound functions in some appropriate way.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is it an anti-pattern to modify JavaScript's built-in prototypes?
I just learned that it's possible to modify the JavaScript core objects, but the same article that told me how to do it suggested that I never should.
Is it a bad thing to modify a core JS object? If so, what problems could this cause?
As an example, here's a modification of the Array object that gives me an easy way to search for a given value in an array:
Array.prototype.search = function(val){
var i;
for (i = 0; i < this.length; i++){
if (this[i] == val) {
console.log("found: " + val);
return true;
}
}
console.log("didn't find it");
return false;
};
Here's the article: Advanced Javascript: Objects, Arrays, and Array-Like objects
Yes, when modifying so-called host objects the behaviour is undefined. It might work (usually it does for objects like Array, String and Object), it might break things.
However, you should never modify the prototype of Array or Object as it will break for(var key in element) for arrays and objects unless you include if(!element.hasOwnProperty(key)) continue; at the beginning of all those loops.
So never do it even if you don't use for..in loops.
Whether is bad or not is quite debatable, I really like the point of view that #kangax gives us in this article:
Extending built-in native objects. Evil or not?
At first he separates the extension of host and native objects, with host objects there are no guarantees, there's no a spec, and they have no rules.
Host objects are those that are provided by the environment, they are not part of the ECMAScript specification, for example DOM objects.
Extending native objects seems "less dangerous", he explores the problems of enumerability, which seems to be a problem, the for-in statement enumerates all object properties, inherited or own, if you add a property on Object.prototype for example, any object used with this statement will show the property name.
This statement is often abused to iterate over array objects, while it's purpose is to enumerate object properties.
At the end, I think the conclusion of this article is that extending native objects to shim standard compliant methods (e.g. ES5 Array methods (map, forEach, reduce, etc)) is encouraged, but extending natives to add custom non-standard compliant methods is discouraged.
The problems usually come from wrong behavior in other libraries or code that don't expect those extra properties.
What you should never touch is Object.prototype as that has a very high chances of breaking any for .. in loop, but an array is usually looped on the items, so it's less risky.
BTW, what you are doing is available in some browsers (at least Firefox) as Array.prototype.indexOf
This will not necessarily cause problems, but if you are working in a production environment it is not recommended. All around, it is general practice to not modify objects that you did not create; take a look at http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
For one, someone using maintaining code might freak out seeing that some code does not behave the way she expects.