0

I want to add a method that is capable of working on all objects. Preferably it should not exist on primitives (number, boolean, string, symbol), on which it cannot work.

Is this possible, and if so, how?

Using Object.prototype does not work because the primitive types inherit from Object.

Daniel Herr
  • 19,083
  • 6
  • 44
  • 61

3 Answers3

3

You can set the function on the prototype of Object, then set the corresponding member on the prototypes of the constructors where you don't want it to undefined:

Object.prototype.foo = function() { alert("foo"); };
Number.prototype.foo = undefined;
var x = {};
var y = 10;
x.foo(); // works
y.foo(); // TypeError: y.foo is not a function

I don't know why you're doing this, and it seems like a code smell, but there you go.

Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
1

Primitives are not objects and don't inherit from anywhere. They can be wrapped in objects which do inherit from Object.prototype, but these are objects.

It might look like primitives inherit properties, but under the hood these are accessed on the object wrappers, not the primitives. When GetValue resolves a property reference,

So if the base of the reference was a primitive, it will be converted to an object before attempting to get the property.

But as @nnnnnn notes, when you call the method, the this value will be the primitive, because the base of the reference didn't change. Note in sloppy mode it will be coerced to an object.

In fact, you could take advantage of this and test whether the this value is an object, if what you want is prevent primitives from being used as bases of references when calling the method:

Object.prototype.method = function() {
  "use strict";
  if(Object(this) !== this) {
    throw Error('This method can only be called on objects');
  }
  // ...
  return "works";
};
true.method(); // Error: This method can only be called on objects
new Boolean(true).method(); // "works"
Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 1
    I understand the distinction you're making, but...even your own example `true.self()` shows that you can take a primitive and directly call the method from `Object.prototype`. (I say "directly" in the sense that in the code you don't explicitly convert or wrap anything, it just "works".) Also, think about what happens if you add `"use strict";` to your function... – nnnnnn Sep 04 '16 at 03:26
0

Streamlined way of removing the method from primitives.

Object.prototype.test = function() { }

for(let { prototype } of [ String, Number, Boolean, Symbol ]) {
 prototype.test = undefined
}
Daniel Herr
  • 19,083
  • 6
  • 44
  • 61