JavaScript Object and Primitive - javascript

Please I want someone to explain the code below for me:
var f = new Number(44);
f.name = "Yusuf";
f.hello = function() {
console.log("Hello");
};
console.log(typeof f);
f.hello();
console.log(f.name);
console.log(f.toString() + "good");
console.log(Object.prototype.hasOwnProperty(name));
console.log(f.hasOwnProperty(hello));
console.log(f.length);
When I check the variable type. Object gets return and I am sure this is because of the Number object constructor call function. I added two properties, one a member and a method and when I call them , it work but when I used hasOwnProperty(), false is return for the member key and undefined for the method key.
Why is it so?
where are the methods going to if the hasOwnProperty doesn't work as usual when it is supposed to when I am actually checking the property on the containing object.?
I checked Number and object object and they all return false.

The hasOwnProperty method takes the property key as a string:
console.log(Number.prototype.hasOwnProperty("name"));
console.log(Object.prototype.hasOwnProperty.call(f, "name"));
console.log(f.hasOwnProperty("name"));
console.log(f.hasOwnProperty("hello"));
I recommend to always "use strict" mode so that you get exceptions when you try to use undeclared variables.

Related

How do I return a specific value to any property or function calls for an object?

I want to calculate the properties of an object based on a string.
But these property definitions might reference another object called 'actor'.
If this actor exists (which is not always the case) my code works, if the actor does not exist (is undefined) I want the evaluation to return NaN for actor-dependant properties.
Example:
The property definition string might look like:
"name = 'pant leg insurance';
cost = 10;
useful = actor.hasPants();
max = actor._legs;"
These variables are defined before the definition string is run through
eval(propertyString);
If the actor exists everything is fine, but if the actor does not exist I want every actor-dependant value (in this case 'useful' and 'max') to return NaN.
I already researched a bit and found the Proxy object, but this only helps if I want to access a direct property of the actor, neither with functions nor with properties which are properties of properties [...] of the actor.
var actor;
if (actor === undefined) {
actor = new Proxy({}, {
get: function(target, property) {
return NaN;
}
});
}
console.log(actor.anything);
console.log(actor.anyfunction());
console.log(actor.anything.anything);
console.log(actor.anything.anyfunction());
How do I achieve that this snippet would return NaN for any property or function calls on actor?
No, proxies cannot achieve this. When a property is accessed, you don't know whether it will be used directly in the assignment or will be called as a method, so you can't decide whether to return NaN or a function. There is no callable NaN value.
Instead, you will need to process your property definition string (you probably want to anyway, as assigning to undeclared variables is evil) and test each line for usage of actor, and when it does apply your if-not-exists-then-NaN logic.

airnb/javascript: What does this mean: "These methods may be shadowed by properties ..."?

I try to understand the following sentence at github airnb/javascript
https://github.com/airbnb/javascript#objects--prototype-builtins
Why? These methods may be shadowed by properties on the object in
question
What is meant with "shadowed" in this case?
For easier reference here the full section:
3.7 Do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf.
Why? These methods may be shadowed by properties on the object in
question - consider { hasOwnProperty: false } - or, the object may be
a null object (Object.create(null)).
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object,key));
// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has';
// ...
console.log(has.call(object, key));
When you creating an object
const anObject = {};
it almost always has the Object in prototype chain. It allow the created object to have access to functions defined in Object like hasOwnProperty.
Shadowed means a method or a property that defined in the created object has the same name as those functions or properties that in prototype chain.
Example of shadowing:
const obj = {};
obj.hasOwnProperty // => ƒ hasOwnProperty() { [native code] }
obj.hasOwnProperty = 'don\'t do this!';
obj.hasOwnProperty // => "don't do this!"
Consider some example below:
const object = { hasOwnProperty: false }
console.log(object.hasOwnProperty(key)) // Error: hasOwnProperty is not a function
or
const object = null
console.log(object.hasOwnProperty(key)) // Error: Can not read property of null
So you can understand shallowed in this case is your object methods in prototype is shallowed by an object property (has the same name)
See an example. Here I have created an function with name hasOwnProperty directly on the my object. So it hides the parent version of the hasOwnProperty. In it I write a logic which will return everytime true. So anybody who will use my object and tries to detect if it has some property in it (he/she doesn't know I have shadowed the base on) he can have a logic errors in his/her code. Because JS will try to find the function first in the object and call that version which actually does another work.
But when you call this method from the Object.prototype, which is the correct version of the method, and pass the context to it, it will work correctly, because it will call the Object.prototypes method with name hasOwnProperty and just pass this object as the context of the method. So from here is the warning that you must use this methods from the prototype.
Actually you can also change the Object.prototype version of the method, but there is a rule, Not change the prototypes of the built in objects.
const object = {
hasOwnProperty: function() {
return true;
}
};
console.log(object.hasOwnProperty('name'));
console.log(Object.prototype.hasOwnProperty.call(object, 'name'));
The first log says that there is a property name in the object, but it isn't. This may cause a logic error. The second one uses the correct version and gives a correct result.

Returning a non-value property

In javascript, it is possible to define an object's property as a getter/setter rather than just a "plain" value:
Object.defineProperty( obj, 'complex_property', {
get: function getter() { return this.protected; },
set: function setter( value ) { this.protected = value; }
} );
Is there any way to return a non-value property of an object without first having its getter function evaluated so that this (or the like) is possible?
obj.property = function( name ) { return this.[ name ]; };
// Doesn't work:
// ReferenceError: invalid assignment left-hand side
obj.property( 'complex_property' ) = 5;
The last line effectively reads 6 = 5 - obviously an error - since this.complex_property is evaluated first, then returned. Combining closures with getter-setter properties is an effective way to simulate "private" properties and validate assignment values without having to use actual get/set functions: one of the nicer features of modern javascript. It'd be even nicer if there was a way to return an unevaluated getter/setter property: is there a way I've missed or is it just not possible? Are we stuck using set( prop, value ) functions?
Unfortunately, this isn't possible with JavaScript functions. All JavaScript functions created by user code can only return values, not references (and this won't be possible by code within the browser too, starting from ES6).
A ReturnStatement is evaluated as follows (bold my emphasis):
If the Expression is not present, return (return, undefined, empty).
Let exprRef be the result of evaluating Expression.
Return (return, GetValue(exprRef), empty).
The only way to do so is either using a set(property, value) function or creating an actual setter.
You can get a property. Well, a property descriptor at least. And it ain't pretty.
var prop = Object.getOwnPropertyDescriptor(obj /* from question */, 'complex_property');
prop.set.call(obj, 5);
edit:
obj.property = function (name) { return Object.getOwnPropertyDescriptor(this, name); }
obj.property('complex_property').set.call(obj, 5);

What is the difference between JavaScript object and primitive types?

Stoyan Stefanov in his excellent book 'Object-Oriented JavaScript' says:
Any value that doesn't belong to one of the five primitive types listed above is an object.
With five primitive types he means Number, String, Boolean, Undefined and Null. However in Google Chrome console it seems like number is not primitive type at all (compared to C primitive types like int). It looks like the primitive number has methods:
var a = 2.2;
console.log(a.toFixed()); // logs "2"
Thus I assumed that I can work with number as with an object, so I tried to assign a property to it:
var a = 2;
a.foo = 'bar';
console.log(a.foo); // logs undefined
I don't understand that behavior. If number has a method, it should behave like object, shouldn't it? It even has a prototype:
Number.prototype.foo = 'bar';
var a = 2;
console.log(a.foo); // logs 'bar'
So what is the magic behind this? How JavaScript treats objects versus primitive types? I would rather not use the word primitive and substitute it with simple objects. As I see it those are objects which can't be extended with new properties, however they are constructed through their constructor and also have prototype which can be extended like with normal objects.
[...] It looks like the primitive number has methods
The primitive, does not actually has its own properties. It gets coerced to an object in order to be able to access "its" properties. The coerced object is not accessable outside the called Method *(In strict mode even not inside the method)*. As such, the referenced variable is always a primitive.
Consider this simple example:
Number.prototype.myTypeInAMethod = function () {
console.log (typeof this.valueOf ()) //"number" => The primitive is wrapped in an object.
return typeof this;
}
var num = 123;
typeof num; //number
num.myTypeInAMethod () //object
side note: In ES5s strict mode,this would be a primitive and the type would be number
Since the variable num is a primitive, you can not assign values to it.
num.foo = "bar";
num.foo //undefined
If you instead create a number (or string) via its object constructor, its type indeed is an object.
A quick check by adding a property shows it can actually be assigned.
var objNum = new Number(123);
typeof objNum ; //"object"
objNum.foo = "bar";
objNum.foo //"bar"
So what is the magic behind this? How JavaScript treats objects versus primitive types?
This process is described in ES5 §8.7.1 GetValue
For an object:
If Type(V) is not Reference, return V.
Let base be the result of calling GetBase(V).
If IsUnresolvableReference(V), throw a ReferenceError exception.
If IsPropertyReference(V), then
If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below.
Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument.
Else, base must be an environment record.
Return the result of calling the GetBindingValue (see 10.2.1) concrete method of base passing GetReferencedName(V) and IsStrictReference(V) as arguments.
For a primitive:
The following [[Get]] internal method is used by GetValue when V is a property reference[1] with a
primitive base value. It is called using base as its this value and with property P as its argument.
The following steps are taken:
Let O be ToObject(base).
Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
If desc is undefined, return undefined.
If IsDataDescriptor(desc) is true, return desc.[[Value]].
Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].
If getter is undefined, return undefined.
Return the result calling the [[Call]] internal method of getter providing base as the this value and providing no arguments.
NOTE The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of the object. The only situation where such an actual property access that uses this internal method can have visible effect is when it invokes an accessor function.
[1] IsPropertyReference(V). Returns true if either the base value is an object or HasPrimitiveBase(V) is true; otherwise returns false.

What is the result of the expression?

Does this code would work as expected in all browsers? Is there any notes in specification about it?
var attributes = this._attributes ? this._attributes : (this._attributes = []);
I.e. if *this._attributes* not initialized, then new array will be created and that array will be assigned to *this._attributes* and to attributes.
There's nothing special about that expression, and you'll have no problems in any major browser. You could shorten it by using the || operator:
var attributes = this._attributes || (this._attributes = []);
That will work in all browsers.
It could be actually made terser with...
var attributes = this._attributes || (this._attributes = []);
No, I think unfortunately you may not access _attributes when it's undefined. So you have to check typeof attributes != "undefined".
I don't see any reason why not. I don't think I'd write it that way, I'm not a fan of assignments with side-effects, but syntactically it's fine.
This works just fine, when accessing an undefined property of any object, that access will return undefined. The single thing you have to watch out for is that you don't extend the Object.prototype to have a _attributes attribute because this will screw you up, but then again, never extend native prototypes.
From the spec :
8.12.2 [[GetProperty]] (P)
Let prop be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
If prop is not undefined, return prop.
Let proto be the value of the [[Prototype]] internal property of O.
If proto is null, return undefined.
Return the result of calling the [[GetProperty]] internal method of proto with argument P.
So it checks whether the object has the property, if so it returns it, if not it searches up the prototype chain, if it finds something there it returns it, otherwise it returns undefined.

Categories

Resources