Why is it that when toString is called on a number it isn't called like a typical function. I would expect var num = 5; toString(num); but instead it is done like var num = 5; num.toString();. Why is a period used to call the function on the number rather than supplying the number as an argument? I know that periods are used to reference properties of an object but I can't see how that applies to this situation. Sorry if this is an easy question, but I am new to programming and I really want to understand the language before I continue.
In JavaScript, the . is used to access a property on an object. In this case, a Number has a property on it toString that is a function you can invoke.
var num = 5;
num.toString //function toString() { [native code] }
num.toString() //"5"
the function toString without anything preceding it is really a property on the window object, and is the equivalent of the following:
window.toString //function toString() { [native code] }
toString() on it's own is actually window.toString() which is Object.prototype.toString.
It does not take any arguments.
console.info(toString === window.toString)
console.info(window.toString())
What you may perceive as global, built-in functions are actually methods of the window instance.
The prototype of the number is defined https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString.
If you use directly the toString, this means that you ask from the global scope to use the global toString ( window.toString()). The window is very generic to know how to convert a specific number to String.
Related
Can someone explain to me the difference of when to use a function by feeding your variables into the parenthesis, and when to tack the function on after the variable with a period, like using the toString() function?
example code
function addMe(a){
a = a+1;
return a;
}
var num = 1;
addMe(num);
num.toString();
I'm not actually sure if my syntax is correct, but I want to know when to feed a variable as a parameter, like how I feed the variable num, to the addMe function. And when to use the function .toString() by putting a period after the variable and typing out the function.
could I have done something like this- provided I built my function correctly?
var num = 1;
num.addMe();
Thanks for the help!
The first is used for simple 'stand alone' functions, while the latter is used for object methods. E.g a number object by default has a toString() method. Some object methods may also require parameters to be passed between the parentheses.
Variables (a function declaration is just a function stored in a variable) are looked up in the scope chain (going up to the next outer scope until a variable with the name is found):
let a = 1; // outer scope
{ // inner scope
console.log(a); // looked up in "inner scope", than "outer scope"
}
Properties of an object are looked up in the objects prototype chain, so if you do
a.b
then a gets looked up in the scopes as explained above, then b is accessed on the resulting object (everything is an object in JavaScript, except for "nothing" (undefined, null)) by looking up the prototype chain. For a simple object, the chain is quite short:
const a = { b: 1 }; // object -> Object.prototype
Here b will be found in the object itself. However all objects inherit from the Object.prototype object, so if you add a property to that (please don't):
Object.prototype.test = 1;
you can then look it up on every object, as the lookup traverses up the prototype chain, and reaches Object.prototype:
console.log({}.test); // 1
Now for numbers (like in your case), they inherit the Number.prototype so you could do:
Number.prototype.addMe = function() {
console.log(this);
};
// two dots are needed to distinguish it from numbers with a fraction (e.g. 1.2)
1..addMe();
That said, now addMe can be called on every number, everywhere in your code. While that might seems useful, it is actually a pain as you don't know where a certain method was added
1..whereDoIComeFrom()
that makes code unreadable and unstructured. Instead if you need a certain functionality multiple times, abstract it into a function, don't touch the native prototypes.
I assume that addMe is just a simplified example, if it isn't, read on:
If you pass an argument to a function in JavaScript, the value will be copied (it is a bit more complicated with non primitives (everything except numbers, booleans etc.)) into the parameter variable of the function called so here:
function addMe(a){
a = a+1;
console.log(a); // 2
return a;
}
var num = 1;
addMe(num);
console.log(num); // 1 ... ?
you actually got two variables (a and num), changing a does not change num. But as you return a you can do:
num = addMe(num);
which copies the value of num into a, then increases a by one and then copues the value of a back to num.
When you did var num = 1 you created a JavaScript object. It looks just like a number but you can think of everything in JavaScript as an object (simplification) and all these objects have different features. So a number has some features, a string has some other features, etc.
You mentioned one feature: toString. Another feature would be toLowerCase.
toString and toLowerCase are functions that come with JavaScript. These functions are then "put on" all of these objects for us to use.
I can have a string variable like
var text = 'MY TEXT'
var lowercaseText = text.toLowerCase()
console.log(lowercaseText) // my text
This code will work because it was decided that the toLowerCase function should work on strings
I can also have an array (list of items)
const list = ['A', 'B', 'C']
const answer = list.toLowerCase()
console.log(answer)
But this code won't work because toLowerCase doesn't work on arrays. So you get the following error message: list.toLowerCase is not a function.
Basically its saying: I don't know what toLowerCase means when used on this list variable (array).
In JavaScript this is called prototypes. Prototype is a way for JavaScript to get some feature from another. Basically: I have all kinds of functions, what object can use what functions. This is called the prototype chain.
In both cases you are using a function. addMe is a function you created and toString is a function in JavaScript that has been placed on objects through this prototype-chain.
Im not actually sure if my syntax is correct
Yes your syntax is correct. Your addMe function is the standard way to create a function in JavaScript.
But i want to know when to feed a variable as a parameter, like how i
feed the variable num, to the addMe function.
Just like you did, you define a function and parameters like you did.
..and when to use the function .toString() by putting a period after
the variable and typing out the function.
When you want to place your function on a object so that all instances of that object can you that object.
In most cases, espcially when you are starting out. You don't have to worry about these prototypes. The way you did.
function addMe(number) {
return number+1
}
const answer = addMe(1) //2
Is a standard way of defining a function and calling it.
I understand that writing
var x = Number("7"); // makes a number, a primitive
var y = new Number("7"); // makes a Number object
and I'm aware of the usual cautions against option 2, but what is going on behind the scenes? I was under the impression if a function is a constructor, it should not return a value via a return statement: it just sets up its implicit object, this, and returns it.
So how come Number, String, and Boolean constructors are able to return either a primitive or an object? Does the JavaScript engine parse those expressions differently as a special feature in the language? Or can a programmer also "overload" a constructor function to either return a primitive or an object, depending on whether the constructor is called with/without "new"?
Using the constructor the Number object will be an object, using the function Number instead will return the conversion of an object to its representation as a numeric value.
So, basically within the Number object, the function is validating how was called. This is possible by checking the object this.
Something interesting is coercing the Number object to a numeric value as follow:
var x = Number("7"); // makes a number, a primitive
var y = new Number("7");
console.log(x === +y)
Go and read about the specification
https://www.ecma-international.org/ecma-262/5.1/#sec-15.7
It has nothing to do with syntax and there's nothing special about those constructors. The Number() and other constructors simply test to see whether this is bound before proceeding.
You can do it too:
function MyConstructor() {
if (!this) return new MyConstructor();
// stuff ...
}
Now calling MyConstructor() will behave exactly like new MyConstructor().
Also, a constructor can return something. If it returns an object, then that's used instead of the implicitly-constructed object that new creates. Thus you could also implement a "new-is-optional" constructor another way:
function MyConstructor() {
let object = this || Object.create(MyConstructor.prototype);
// stuff ...
return object;
}
So the Number() constructor takes a different tack. In most runtimes it may or may not actually be implemented as JavaScript, but if it were it might look something like this:
function Number(n) {
if (this) {
// invoked with "new"
this.fantasyValueSetter(n); // cannot really do this
return this;
}
return +n; // plain number primitive if not invoked with "new"
}
Similar to this question, I am following Douglas Crockford's JavaScript, The Good Parts. In chapter 4, he talks about augmenting types, which I find very confusing. He writes this sample code:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Number.method('integer', function ( ) {
return Math[this < 0 ? 'ceil' : 'floor'](this);
});
He then tests the new integer method:
document.writeln((-10 / 3).integer()); // -3
I don't understand the syntax of this.prototype[name] (in particular, the brackets) or Math[this < 0 ? 'ceiling' : 'floor'](this) (again, the brackets and also where Math came from). More importantly, can someone explain how the code in general works, and why the test code works?
By extending Function.prototype you add a method available to every function. Remember that functions in JavaScript are objects, and as such they can have properties and methods eg. call or apply.
The method function method lets you add a method to the prototype of any given function. Number is a function; the constructor of numbers, which has a prototype. Functions that you add to the prototype are available for all instances of the object, in this case a number.
Math is a built-in object in JavaScript, by using bracket notation you can dynamically access the property of an object. Remember that object keys are just strings, even if you don't write them as string, they can still be accessed with bracket notation with a string, for example:
var obj = {
key: 'hello'
};
var k = 'key';
obj[k]; //=> 'hello'
In the case of Math it's simply deciding if it should use ceil (not "ceiling") or floor based on a condition, you could write like this:
if (this < 0) {
Math.ceil(this);
} else {
Math.floor(this);
}
Javascript is weird.
In most languages you do foo = someObject.someMember and JS allows that too.
But it also lets you do foo = someObject["someMember"] which seems silly... until you realize that the string could be replaced with a variable
var memberName="someMember"
foo = someObject[memberName]
Now you're able to write very dynamic code that can leverage object members without knowing the names of those members when you write the code. This is what the code you posted is doing. It feels dirty at first but that feeling will pass ;)
Can anyone please explain this code? This example is taken from javascript.info.
I don't understand, especially the f.toString = function(){ return sum} part.
function sum(a) {
var sum = a
function f(b) {
sum += b
return f
}
f.toString = function() { return sum }
return f
}
alert( sum(1)(2) ) // 3
alert( sum(5)(-1)(2) ) // 6
alert( sum(6)(-1)(-2)(-3) ) // 0
alert( sum(0)(1)(2)(3)(4)(5) ) // 15
I think the author of that snippet wanted to achieve one goal, that is, something like "faking" operator overloading which is possible in other languages.
Since sum returns a function reference, we could not go like
sum(5) + 5;
That would result in something weird like "function sum() { ... }5". That is because ECMAscript calls the .toString() method on objects when invoked in a Math operation. But since he overwrites the .toString() method returning sum (which is a number), it does work again.
All objects in javascript 'inherit' a field called toString that exists on the prototype of boject. After assignment toString exists as any other field on f. It is assigned a as a function, and can be invoked as such:
Basically, sum is a function that can be chained into multiple calls. toString is a method of the object that returns what should be shown if the object is used in a context that expects a string.
Personally, I think it'd be easier like this:
function sum() {
var l = arguments.length, i, a = 0;
for( i=0; i<l; i++) a += arguments[i];
return a;
}
alert(sum(1,2));
alert(sum(5,-1,2));
alert(sum(6,-1,-2,-3));
alert(sum(0,1,2,3,4,5));
Here is a snippet from MDN article about Function.toString
The Function object overrides the toString method inherited from
Object; it does not inherit Object.prototype.toString. For Function
objects, the toString method returns a string representation of the
object in the form of a function declaration. That is, toString
decompiles the function, and the string returned includes the function
keyword, the argument list, curly braces, and the source of the
function body.
JavaScript calls the toString method automatically when a Function is to be represented as a text value, e.g. when a function is
concatenated with a string.
So basically, what this "annoying" piece of code is doing is providing an implementation for Function.toString that will be used when when a string representation is required, i.e. when alert is called (alert takes a string as an argument).
For the rest of the code, it's just calling itself recursively to compute the sum of the arguments.
I want to extend the type 'Number' with a new function and hence I have to define a prototype. When I think about this, I get a bunch of questions:
Does Number inherit from both Object.prototype as well as Function.prototype?
Is 'Number' an 'Object' or a 'Function'?
When should I define an object as a prototype for Number? Does it make sense?
1- True. Number instanceof Object returns true also Function instanceof Object returns true. So Number has all methods that Object and Function has.
2- Number is a function. typeof Number returns "function".
3- If you want to add a method to Number's prototype, just use
Number.prototype.METHOD_NAME = function() {
// your logic
}
Then you can call your method on all numbers like 1..METHOD_NAME()
The number methods are already contained in Number.prototype to add own methods just do:
Number.prototype.addOne = function(){
return this.valueOf() + 1;
};
1..addOne() // 2
Your question confuses me as I am not sure whether by Number you mean the number constructor which is just an ordinary function or number primitives.
Number primitives are not objects and as such don't inherit anything, when you do 1..addOne() the number is converted to an object and then the .addOne is found in the Number.prototype and called with this set to the object form of the number.
Number itself is an ordinary function.
You can assign properties to it directly.
If you want to extend number instances, you should assign to Number.prototype.
I don't understand your questions. If I really thought monkey-patching Number was a good idea, I'd just do:
Number.prototype.newfunc = function(...) { ... }
Number, Function and Object are all General-purpose constructors. Number inherit from Function which in turn inherits from Object. Number constructor should be used for number primitive to create wrapper object and invoke associated functions.