Why 1["foo"] returns undefined instead of an error? [duplicate] - javascript

This question already has answers here:
How and why does 'a'['toUpperCase']() in JavaScript work?
(12 answers)
Why is 0[0] syntactically valid?
(7 answers)
Closed 4 years ago.
Today I came accross a strange thing in Javascript.
When in Chrome console if I execute :
> 1["foo"]
Chrome console returns :
undefined
I was expecting an error though. How is it possible? I fall on that by studying the underscore.js (an old version) invoke method that seems to use that JavaScript property:
// Invoke a method (with arguments) on every item in a collection.
_.invoke = function(obj, method) {
var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method);
return _.map(obj, function(value) {
var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
});
};
As you can see, value could be a number and if 1["foo"] was raising an error, that code would be unsafe as I could do the following by mistake:
var a = {'foo' : 1}
_.invoke(a, 'foo'}

Everything, even primitives, are essentially objects and can have members (properties, methods, etc). All the code in question is doing is attempting to find a member on 1 with the name foo which is not found so undefined is returned.

Related

Nodejs' try (check) for undefined [duplicate]

This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
Closed 2 years ago.
In ruby we something like a.try(:property) even if a is nil(undefined) program won't throw an exception and keep going. But for nodejs/javascript if I have a.property and a is undefined program will throw an exception. I have to do something like
if (a) {
a.property
}
It is quite tedious and unpretty.
Is there something in nodejs similar like a.try(:property) so I don't have to check before I use a property?
I dont think there's any function like that in node.js. But you could build your own utility function like this...
// utility function
let tryProp = (a, p) => ( a? (a[p] ? a[p] : null) : null);
// Testing if property exists.
let x;
x = { key: "value"};
console.log(tryProp(x, 'john')); // returns null
console.log(tryProp(x, 'key')); // returns value
// Incase variable is undefined
let y;
console.log(tryProp(y, 'key')); // returns null

Why do I need to bind a shadowed function that is called through the same object? [duplicate]

This question already has answers here:
How does the "this" keyword in Javascript act within an object literal? [duplicate]
(4 answers)
Closed 4 years ago.
Was doing some dirty things to Array.prototype when I ran into this:
Array.prototype.hook_pop = function(callback) {
var base_pop = this.pop.bind(this); //<-- this works
var base_pop = this.pop; //<-- this doesn't work
this.pop = function() {
var ret = base_pop();
callback(ret, this);
return ret;
}
}
Initially I tried using the non-working option and got an error "Uncaught TypeError: Cannot convert undefined or null to object".
The way I've understood it, unless otherwise bound, "this" should point to the object through which the method is called from, in this case the array instance. When called on the same object though, either way, "this" should be the same when being passed to the pop function, whether its bound or not. Why doesn't the second option work?
var ret = base_pop();
In this line you're invoking base_pop() by itself, and not as a method of any object. Because of this, its this value isn't set.

Using a "shortcut" function gives me a "Illegal invocation” error [duplicate]

This question already has answers here:
"Uncaught TypeError: Illegal invocation" in Chrome
(4 answers)
Closed 6 years ago.
I'm having this code in Javascript ES6:
// Create a new object
var foo = new A();
// Create shortcuts to use localStorage faster
foo.set = window.localStorage.setItem;
foo.get = window.localStorage.getItem;
// Try to use localStorage
foo.set('count', 1);
But I get "Illegal invocation” for the last line, and I don't understand why.
Any idea how to fix this?
You are changing the methods context of this. Use Function#bind to set this to localStorage:
var foo = {};
undefined
foo.set = window.localStorage.setItem.bind(localStorage);
foo.get = window.localStorage.getItem.bind(localStorage);
// Try to use localStorage
foo.set('count', 1);
console.log(foo.get('count'));
Alternatively you can create a wrapper function that invokes the localStorage functions.
foo.set = (k,v) => window.localStorage.setItem(k,v)
foo.get = (k) => window.localStorage.getItem(k)

Store extra properties in a javascript integer [duplicate]

This question already has answers here:
Javascript assigning value to primitive
(2 answers)
Closed 8 years ago.
Consider this excerpt from a node.js REPL session:
> var a = 5;
undefined
> a.b = true;
true
> a.b;
undefined
The intention is to store extra properties in a, which if successful would make the final line be true instead of undefined. How can I do this?
You cannot do that. A number is not an object in JavaScript. When you write:
a.b = true;
what happens is that the runtime instantiates a Number instance automatically. That's an object. You set the "b" property on that object to true, and then it's forgotten.
Now, you can do this:
var a = new Number(5);
a.b = true;
alert(a.b);
and it'll work just fine.

.bind function with CoffeeScript [duplicate]

This question already has answers here:
Ember computed properties in Coffeescript
(3 answers)
Closed 10 years ago.
When I try to convert the following snippet of code ...
result.pause = function() {
cachedValue = this();
isPaused(true);
}.bind(result);
using http://js2coffee.org/ it returns
result.pause = ->
cachedValue = this()
isPaused true
.bind(result)
However that code is incorrect when you try to compile it you get back Error Unexpected '.'
What would the correct way to use the .bind function in this situation using CoffeeScript be?
result.pause = (->
cachedValue = this()
isPaused true)
.bind(result)

Categories