I'm trying to refresh some Javascript knowledge for an upcoming interview. I was reading a blog that says
"The delete operator returns true if the delete was successful."
and then shows an example of it in use:
var christmasList = {mike:"Book", jason:"sweater" }
delete christmasList.mike; // deletes the mike property
In that example it looks like delete is used in the manner that a void function (in the general programming sense -- I know that JS doesn't require declarations like void) would be.
Can someone explain to me, or give me a link to, the documentation that explains how JS functions can act with different return values, and does such require separate implementations for each return value?
You can check the Delete operator which says:
If desc.[[Configurable]] is true, then
Remove the own property with name P from O.
Return true.
Note that delete only works for properties of objects. Also a good read:- JavaScript Delete() Only Affects The Referenced Object Regardless Of Prototype Chain
In that example it looks like delete is used in the manner that a void function
The delete operator is not a function, it is an operator. It deals with properties of objects, not their values.
Functions are something else, but since you asked:
Can someone explain to me how JS functions can act with different return values
JavaScript is loosely typed. Functions don't care about the types of values unless they need to, and (most of the time) conversion between types is handled by operators.
If a function needs to are about what it is operating on, then it has to examine the value to see what it is.
For example:
function myFunction(myArgument) {
if (typeof myArgument === "function") {
return myArgument();
} else {
return myArgument;
}
}
A function can return any value it likes.
function string_or_number() {
if (Math.random() > 0.5) {
return 1;
} else {
return "1";
}
}
Strongly typed languages care about what type of value a function returns and what type of value is passed into an argument.
Loosely typed ones simply don't. There's nothing special about it from the point of view of someone using the language.
It shunts most of the complexity about having to care about types to the compiler author instead of the user of the compiler (who just has to care that, if a function is designed to do something to a duck, what they pass is sufficiently like a duck to not break the function).
As others note, delete is technically an operator and not a function; for our immediate concerns, however, the difference is academic, as the operator's behavior is the same as that of many functions used for their side effects (which is to say, void functions). Both the rule of the language and the conventions of their use are simple.
Rule
All functions provide a return value; if no return statement is reached, this will be undefined
Conventions
Since we always get a return value, we can take advantage of it to improve our programs. There are two conventions; which one should be used depends on the use case.
Return a boolean, signalling success or failure
Return some object being operated on
Option 2 is most useful for methods on objects: if our method changes the state of the object and then returns the object, we can bundle several changes into a single line of method calls: object.change1().change2().change3(newVal);
Option 1 is most useful when we want to use the success or failure of an operation to determine program flow; maybe we want to throw an exception if the property was not deleted but continue normally if it was. Then we can use if (delete object.property) to attempt to delete the property and branch into success/failure cases immediately.
From the MDN on the delete operator:
Throws in strict mode if the property is an own non-configurable property (returns false in non-strict). Returns true in all other cases.
I can't make it simpler than that. Aside from a small example:
alert(delete window.window)
alert(delete window.foobar)
alert(delete window.alert)
Javascript functions always return ambigious values. One function can return boolean, string, object, array or HTMLElement.
There is no fixed type.
function masterSwitch(input) {
switch(input) {
case 0 : return "Hello";
case 1 : return 0xdead;
case 2 : return 0.00042;
case 3 : return document.createElement("DIV");
case 4 : return true;
case 5 : return window;
case 6 : return this;
case 7 : return null;
default:window.alert("Please specify input from 0 to 8");
}
}
<input type="text" id="output"> <SELECT onchange="document.getElementById('output').value = typeof masterSwitch(this.selectedIndex);">
<option>string</option>
<option>int</option>
<option>float</option>
<option>HTMLElement</option>
<option>boolean</option>
<option>window</option>
<option>this</option>
<option>null</option>
</select>
Related
I am reading a code written in Typescript. I'm not sure if I understand it correctly:
export class MyClass<B> {
value: B;
constructor(value: B) {
this.value = value;
}
isMyClass(): this is MyClass<B> {
return true;
}
}
What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
isMyClass() {
if (this is MyClass) {
return true;
}
else {
return false;
}
}
And I am not able to find the answer to a these questions.
What does the <B> stand for? What does it represent, a Type? If so, what Type is it?
That's a type parameter, also known as generics. See the TS handbook.
In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.
Whenever one calls a function or creates an instance, if the function or class is generic, you can "pass" a type parameter to it, similar to how arguments can be passed to a function or constructor. (The difference is that the type parameter, being a type, doesn't exist in the emitted JS - it's just there to help TS type-check).
If so, what Type is it?
It's whatever type the constructor parameter is called with.
const m = new MyClass(3);
will result in
constructor(value: B)
where value is 3, telling TypeScript that the resulting instance is a MyClass<number> - in other words, that its value property holds a number, a B.
What is this is MyClass<B> in isMyClass(): this is MyClass<B>? Is it being evaluated for true or false? Why not to put this inside of the function itself then, something like this:
The
isMyClass(): this is MyClass<B> {
is a type guard. If the method returns true, it tells TypeScript that the instance is of type MyClass<B>.
While you could do something like:
isMyClass() {
if (this instanceof MyClass) {
return true;
}
else {
return false;
}
}
That wouldn't allow TypeScript to understand that the type has been narrowed when isMyClass is called; it'll just return a boolean. In contrast, using the is will both return a Boolean and give TypeScript type information about what was called.
I am trying to extend the Number object with this code:
Number.prototype.isNumber = function(i){
if(arguments.length === 1){
return !isNaN(parseFloat(i)) && isFinite(i);
} else {
return !isNaN(parseFloat(this)) && isFinite(this);
}
}
try {
var x = 8.isNumber();
} catch(err) {
console.log(err);
}
I get SyntaxError: identifier starts immediately after numeric literal
also when I try the following:
Number.isNumber(8)
I get Number.isNumber is not a function!!
The JavaScript parser reads 8.isNumber as a number literal.
To access a Number method on a numeric literal you'll have to surround the number with parenthesis so the JavaScript interpreter knows you're trying to use the number properties.
Number.prototype.isNumber = function(i) {
if (arguments.length === 1) {
return !isNaN(parseFloat(i)) && isFinite(i);
}
return !isNaN(parseFloat(this)) && isFinite(this);
}
try {
var x = (8).isNumber();
console.log(x);
} catch(err) {
console.log(err);
}
I couldn't help it but provide an additional answer although you already accepted one.
The first thing you need to know, is that there is a fundamental difference between the Number object, and the Number prototype (see here).
As it stands, you are extending the Number prototype, not the object itself! Your isNumber implementation actually has the same effect like the following:
Number.prototype.isNumber = function(){return isFinite(this)}
Why? Because in order to execute this prototype method, the parser first needs to know the type of the literal you are invoking the function on. That's why you either need to turn your number literal into an expression by wrapping it in parentheses: (8).isNumber() or by using an even weirder notation 8..isNumber() (the first . is the decimal point, the second the property accessor). At this point, the javascript engine already evaluated it as a Number and thus can execute the isNumber() method.
On the other hand, although at first glimpse your code looks like it could handle the following case correctly (since you are doing a parseFloat): "8".isNumber() will always throw an exception, because here we have a string literal, and the String prototype does not have the according method. This means, you will never be able to detect numbers that are actually string literals in the first place.
What you instead should do, is directly extend the Number object so you can actually do a proper check without having to deal with errors:
Number.isFiniteNumber = function(i){
return !Number.isNaN(i) && Number.isFinite(i);
}
Number.isFiniteNumber(8); // returns true
Number.isFiniteNumber("3.141"); // returns true
Number.isFiniteNumber(".2e-34"); // returns true
Number.isFiniteNumber(Infinity); // returns false
// just for informational purposes
typeof Infinity === "number" // is true
Bonus material:
Extending native objects is potentially dangerous.
Number.isNaN() probably does not what you think it does.
I have seen two ways of detecting whether a UA implements a specific JS property: if(object.property) and if('property' in object).
I would like to hear opinions on which is better, and most importantly, why. Is one unequivocally better than the other? Are there more than just these two ways to do object property detection? Please cover browser support, pitfalls, execution speed, and such like, rather than aesthetics.
Edit: Readers are encouraged to run the tests at jsperf.com/object-detection
if(object.property)
will fail in cases it is not set (which is what you want), and in cases it has been set to some falsey value, e.g. undefined, null, 0 etc (which is not what you want).
var object = {property: 0};
if(object.isNotSet) { ... } // will not run
if(object.property) { ... } // will not run
if('property' in object)
is slightly better, since it will actually return whether the object really has the property, not just by looking at its value.
var object = {property: 0};
if('property' in object) { ... } // will run
if('toString' in object) { ... } // will also run; from prototype
if(object.hasOwnProperty('property'))
is even better, since it will allow you to distinguish between instance properties and prototype properties.
var object = {property: 0};
if(object.hasOwnProperty('property')) { ... } // will run
if(object.hasOwnProperty('toString')) { ... } // will not run
I would say performance is not that big of an issue here, unless you're checking thousands of time a second but in that case you should consider another code structure. All of these functions/syntaxes are supported by recent browsers, hasOwnProperty has been around for a long time, too.
Edit: You can also make a general function to check for existence of a property by passing anything (even things that are not objects) as an object like this:
function has(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
Now this works:
has(window, 'setTimeout'); // true
even if window.hasOwnProperty === undefined (which is the case in IE version 8 or lower).
It really depends what you want to achieve. Are you talking about host objects (such as window and DOM nodes)? If so, the safest check is typeof, which works for all host objects I know of:
if (typeof object.property != "undefined") { ... }
Notes:
Avoid object.hasOwnProperty() for host objects, because host objects are not obliged to inherit from Object.prototype and therefore may not have a hasOwnProperty() method (and indeed in IE < 9, they generally do not).
A simple Boolean coercion (e.g. if (object.property) { ... }) is a poor test of the existence of a property, since it will give false negatives for falsy values. For example, for an empty textarea, if (textarea.selectionStart) { ... } will not execute the block even though the property exists. Also, some host object properties throw an error in older versions of IE when attempting to coerce to a Boolean (e.g. var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }).
The in operator is a better test of the existence of a property, but there are once again no guarantees about support for it in host objects.
I recommend against considering performance for this kind of task. Choose the safest option for your project and only optimize later. There will almost certainly be much better candidates for optimization than property existence checks.
For more background on this, I recommend this excellent article by Peter Michaux.
Definitely if ('property' in object) is the right way to go. That actually tests if the property is in the object (or in its prototype chain, more on that below).
if (object.property) on the other hand, will coerce 'property' into a truth/flase value. If the property is unset, it will return "undefined", which will be coerced into false, and appear to work. But this will also fail for a number of other set values of properties. javascript is notoriously inconsistent in what it treats as truthy and falsy.
Finally, like I said above, 'property' in 'object' will return true if it's in anywhere in the prototype chain. If you want to test that's on the object itself, and not somewhere higher up in the chain, you use the hasOwnProperty method like so:
if (object.hasOwnProperty('property')) ...
The first one would fail if "property" is false of 0. To make sure that there actually exist a property you need to check that object.property !== undefined, or use the in-keyword.
[Edit]
There is also the hasOwnProperty-function, but I've never really used that one so I can't say much about it. Though I think it won't return true if the property is set in a prototype, which sometimes you want, other times you don't want.
This allows you to use window.hasOwnProperty as either referring to itself or something else, regardless of your scripting host.
// No enclosing functions here
if (!('hasOwnProperty' in this))
function hasOwnProperty(obj, prop) {
var method = Object.prototype.hasOwnProperty;
if (prop === undefined)
return method.call(this, obj);
return method.call(obj, prop);
}
//Example of use
var global = global || this; //environment-agnostic way to get the global object
var x = 'blah';
WScript.Echo(global.hasOwnProperty('x') ? 'true' : 'false'); //true
//Use as non-object method
var y = { z: false };
WScript.Echo(hasOwnProperty(y, 'z') ? 'true' : 'false'); //true
WScript.Echo(hasOwnProperty(y, 'w') ? 'true' : 'false'); //false
// true ಠ_ಠ
WScript.Echo(hasOwnProperty(global, 'hasOwnProperty') ? 'true' : 'false');
I'm working with XULRunner and came across the following pattern in a code sample:
var StrangeSample = {
backingStore : "",
get foo() { return this.backingStore + " "; },
set foo(val) { this.backingStore = val; },
func: function(someParam) { return this.foo + someParam; }
};
StrangeSample.foo = "rabbit";
alert(StrangeSample.func("bear"));
This results in "rabbit bear" being alerted.
I've never seen this get/set pattern used in Javascript before. It works, but I can't find any documentation/reference for it. Is this something peculiar to XUL, a recent language feature, or just something I missed? I'm puzzled because I was specifically looking for something like this a few months ago and couldn't find anything.
For reference, removing "get" or "set" results in a syntax error. Renaming them to anything else is a syntax error. They really do seem to be keywords.
Can anyone shed some light on this for me, or point me towards a reference?
As suggested by Martinho, here are some links explaining the getter/setters in JS 1.5:
http://ejohn.org/blog/javascript-getters-and-setters/
http://ajaxian.com/archives/getters-and-setters-in-javascript
Be aware though, they don't seem to be supported in IE, and some developers have (legitimate) concerns about the idea of variable assignment having side-effects.
get/set are not reserved keywords as Daniel points out. I had no problem creating a top-level functions called "get" and "set" and using the alongside the code-sample posted above. So I assume that the parser is smart enough to allow this. In fact, even the following seems to be legitimate (if confusing):
var Sample = {
bs : "",
get get() { return this.bs; },
set get(val) { this.bs = val; }
}
According to Mozilla, they are not in ECMAScript.
JavaScript Setters And Getters:
Usually the setter and getter methods follow the following syntax in JavaScript objects. An object is created with multiple properties. The setter method has one argument, while the getter method has no arguments. Both are functions.
For a given property that is already created within the object, the set method is typically an if/else statement that validates the input for any time that property is directly accessed and assigned later on via code, a.k.a. "set". This is often done by using an if (typeof [arg] === 'certain type of value, such as: number, string, or boolean') statement, then the code block usually assigns the this.(specific)property-name to the argument. (Occasionally with a message logging to the console.) But it doesn't need to return anything; it simply is setting the this.specific-property to evaluate to the argument. The else statement, however, almost always has a (error) message log to the console that prompts the user to enter a different value for the property's key-value that meets the if condition.
The getter method is the opposite, basically. It sets up a function, without any arguments, to "get", i.e. return a(nother) value/property when you call the specific-property that you just set. It "gets" you something different than what you would normally get in response to calling that object property.
The value of setters and getters can be easily seen for property key-values that you don't want to be able to be directly modified, unless certain conditions are met. For properties of this type, use the underscore to proceed the property name, and use a getter to allow you to be able to call the property without the underscore. Then use a setter to define the conditions by which the property's key-value can be accessed and assigned, a.k.a. "set". For example, I will include two basic setters and getters for this object's properties. Note: I use a constant variable because objects remain mutable (after creation).
const person = {
_name: 'Sean';
_age: 27;
set age(ageIn) {
if (typeof ageIn === 'number') {
this._age = ageIn;
}
else {
console.log(`${ageIn} is invalid for the age's key-value. Change ${ageIn} to/into a Number.`);
return 'Invalid Input.';
}
},
get age() {
return this._age;
},
set name(nameIn) {
if (typeof nameIn === 'string') {
this._name = nameIn;
} else {
console.log(`Change ${nameIn} to/into a(ny) String for the name's
key-value.`);
return 'Invalid Input.';
}
},
get name() {
return this._name;
}
};
Where it gets interesting is when you try to set/assign a new key-value for the _age property, because it has to meet the if conditional in order to be successfully assigned, meaning not all assignments are valid, etc.
person.age = 'twenty-eight'; /* output: twenty-eight is invalid for the
age's key-value. Change twenty-eight to/into a Number. */
console.log(person.age); // output: 27 (twenty-eight was never assigned)
person.age = 28; // output: none
console.log(person.age); // output: 28
Note how I was able to access the person._age property via the person.age property thanks to the getter method. Also, similar to how input for age was restricted to numbers, input for the name property is now restricted/set to strings only.
Hope this helps clear things up!
Additionally, some links for more:
https://johnresig.com/blog/javascript-getters-and-setters/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
https://www.infragistics.com/community/blogs/infragistics/archive/2017/09/19/easy-javascript-part-8-what-are-getters-and-setters.aspx
If I have a javascript class which cannot be instantiated what should the constructor return that I can test for. The constructor always returns an object so I cannot return null if the constructor fails.
function SomeClass(id) {
if(typeof(id) === 'number' {
// This is good
this.id = id;
} else {
// This is bad
// This return is ignored and an empty object is returned
return null;
}
}
var a = new SomeClass('badParam');
if(a){
// is true even though the class expects a number.
}
// Could use this check
if(a.id !== undefined){
// Do some stuff
}
but it seems there should be a better way.
It is probably best to throw an exception to notify the caller that the initialization failed and to take appropriate action.
Return codes are fine, but for the most part there is no motivation for the caller to implement the checks on the return code.
My advice is to break hard and break soon. This will make contract violations very evident during testing.
Returning any non-object from the constructor is practically the same as exiting the constructor. (The constructor will return a new object, with a prototype if one was specified.)
So, returning null, undefined, or 42 from the constructor are equivalent.
Check out section 13.2.2 of the ECMAScript spec (pdf) for more info.
My first approach:
Don't allow a constructor to fail; consider alternatives
My second approach:
If a constructor fails, it must only fail because of a programming error and thus;
should throw an exception and;
must not return 'a status code' (see Emmett's answer for why returning null doesn't work anyway)
I have never designed a constructor (something invoked as the target of new) to return anything except an object of the "expected" type.
Fail fast, avoid being too clever, and save time debugging hard-to-find bugs.
Happy coding.
Use I sentinel. I like to
return {invalid:true};
This looks clean:
var x = new X();
if (x.invalid) { // ...
(There's no way to return a non-true value from a constructor, so you can't put new in the conditional as you might with another language.)