Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a function to a member of a number, why is that not a failure?

From my Chrome interpreter:

a = 3; // OK, of course.
a.f = function() { return 4; }; // OK. To a number? Ok
a; // Prints 3
a.f(); // f is not a function.
a.f; // Undefined

Of course, a is not an object, and I cannot assign new members to something that isn't an object. But, why does the interpreter swallows the a.f assignment if after that the method or the member doesn't even exist?

like image 202
Peregring-lk Avatar asked Nov 21 '16 22:11

Peregring-lk


People also ask

Is not a function type error?

A TypeError: "x" is not a function occurs when a function is called on an object that does not contain the called function. When calling a built-in function that expects a callback function argument, which does not exist. When the called function is within a scope that is not accessible.

Is not a function meaning?

The JavaScript exception "is not a function" occurs when there was an attempt to call a value from a function, but the value is not actually a function.

Is not a function error react?

The React. js "Uncaught TypeError: X is not a function" occurs when we try to call a value that is not a function as a function, e.g. calling the props object instead of a function. To solve the error, console. log the value you are calling and make sure it is a function.


2 Answers

If you look at 8.7.2 of the ECMA 5.1, you will notice this note at the bottom:

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 that transient object. The only situations where such an actual property assignment that uses this internal method can have visible effect are when it either invokes an accessor function or is in violation of a Throw predicated error check. When Throw is true any property assignment that would create a new property on the transient object throws an error.

Step 1 is Let O be ToObject(base).

If you look at the ToObject() method in 9.9, you will find these two rows in the table:

  • Number

Create a new Number object whose [[PrimitiveValue]] internal property is set to the value of the argument. See 15.7 for a description of Number objects.

  • Object

The result is the input argument (no conversion).


So it looks like when you attempt to set the function on the number, it is actually happening (although as a noop), it just becomes unaccessible after the assignment, due to the assignment happening on an internal transient object. When you do it on a regular object, it returns the actual object, so the assignment makes sense.

like image 199
Matt Way Avatar answered Oct 26 '22 22:10

Matt Way


There's not really a good reason why it wasn't forbidden, it could easily have been if that was how it was implemented when the language was developed.

But why was it implemented without an error? Because it nicely mirrors what happens when you access a property on a primitive: it does implicitly get cast to an object. It doesn't matter whether you use the property reference for assignment or for retrieval, there's an object involved. The assignment will work as usual, even if the coerced object is thrown away immediately afterwards.

We even can see that when we provide an inherited accessor for that object on its prototype:

"use strict";
Object.defineProperty(Number.prototype, "f", {
    set: function(value) {
        console.log(typeof this+" "+this+" got "+value+" assigned to .f");
    },
    get: function() {
        console.log(typeof this+" "+this+"'s .f property was accessed");
        return function() {
            console.log("method called on "+typeof this+" "+this);
        };
    },
    configurable: true
});

(3).f = "test value";
(3).f();
like image 27
Bergi Avatar answered Oct 26 '22 22:10

Bergi