0

We want a function that can apply methods to the input object.

First, we create a function.

$ = function () { /* Constructor Code */ };

Then, we add a method. For example, type. The method will use this function:

function () { return toString.call(this).slice(8, -1);

Finally, we test the function to see if we get the right output. This is what we want to see:

$("test"); // Output: "test"
$("test").type(); // Output: "String"
$(document.body).type(); // Output: "HTMLBodyElement"

The only way the output should differ from the input is an application of methods.

Using Object.addProperties won't work, as it converts the input into an object:

$("test").type(); // Output: "Object"

Also, using an eval-related method won't work either, as some objects don't convert to strings:

$(document.body).type(); // Error: Can't convert element to string!

The same goes for adding an object's properties manually to the object.

$("test").type(); // Can't apply function to literal string!

The question is, what do we do?

1 Answer 1

2

One way is to apply methods to the primitive version of the input.

This is done with Object.assign. Here's a quick implementation:

$ = function (_) {
  return Object.assign(_, {
    type: function () { return toString.call(this).slice(8, -1) }
  })
};

And here's the output:

$("test").type() // Output: "String"
$(document.body).type() // Output: "Date"

We could also use a variable as the method list, which would return the same output:

$ = function (_) {
  return Object.assign(_, $.methods)
};

$.methods = ({
  type: function () { return toString.call(this).slice(8, -1) }
});

However, these solutions both require valueOf to retrieve the original input for certain objects:

$("test"); // Returns a "pseudo-string"
$("test").valueOf(); // Output: "test"

Since valueOf can be insecure, we can add a property to the method list to get the original input:

$ = function (_) {
  return Object.assign(_, ({
    type: function () { return toString.call(this).slice(8, -1) }, val: _
  });
};

And now using val will return the original output without a function call:

$("test").val // Output: "test"
$(document.body).val // Output: <body>...</body>

It's not bad, but maybe there's a way to return a truly unmodified value with the methods?

Sign up to request clarification or add additional context in comments.

4 Comments

This is an interesting concept, but I'm not entirely sure how applicable it would be. You're coercing the value they pass in to the object form of the primitive type (via Object.assign) and then adding a property onto that instance of the primitive object. Your type appears to be unchanged, however, it is not. Number(5) === 5 // true, however $(5) === 5 // false. Also typeof 5 // "number", and typeof $(5) // "object". Furthermore Number(5) === $(5) // false
@mhodges in response to your clarification, I've added more to the answer.
As to the question you have added at the end of your revised answer - the way to do this is to simply use an object wrapper exactly as jQuery does. The unfortunate things is that you then have to use an accessor method to get the original value, but internally, you can leverage closures to access the original, unmodified value. You can actually do it here as well by saying toString.call(_).slice(8, -1) instead of using the this context
Here's a basic example replicating the functionality you have above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.