Restrict object method override in javascript

Asked

Viewed 257 times

4

I’m trying to create an object where your methods can’t be changed. That is, its value, even if modified, should continue as originally defined.

Example:

var object = (function(object){

      object.method = function (text) {
          return 'response ' + text + '!!!';
      }

})({});

I can access it as follows:

object.method()

But it is possible to change the method by simply doing this:

 object.method = null
 //TypeError: object is not a function

Already in the jQuery, when we make this change attempt, the html method continues to do the same thing for which it was designed.

$('body').html = null
$('body').html() // funciona normalmente

Unless you save the value of $('body') in a variable:

$body = $('body');
$body.html = null;
////TypeError: object is not a function

In the first example used with jQuery, how does it internally keep the methods intact? It always creates a new instance?

How to block the rewriting of an object’s methods?

  • Restricting has no way, because jQuery does not protect anything, you can still do what you want with pure JS. If you use the resource right, it helps you not to screw up. What you can do is create ways to help you don’t screw up, but if you want, you can.

  • @Bignow, I remembered a guy named Object.freeze. Did he solve the problem?

  • For what you are saying, no. It only prevents the structure of the object from being modified. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

  • Object.freeze and Object.seal are options that ECMA5 makes possible, but there are alternatives. I will take a look here later to see what has already been said. Good question.

  • I gave an answer, but from the comments above I think I may have misunderstood the question... Do you want to know how to prevent an object’s property/method from being changed, or do you want to know how jQuery works? I left a note about it at the end of my reply, but if you want I can elaborate more...

  • @mgibsonbr I just know that someone got it wrong, who I wouldn’t risk :) Anyway the answer is good.

Show 1 more comment

2 answers

6


You can use Object.defineProperty so as to have greater control over the characteristics of your method (or field). For example, to make your method read-only, assign writable as false:

var object = (function(object){

      Object.defineProperty(object, 'method', {
          value:function (text) {
              return 'response ' + text + '!!!';
          },
          writable:false
      });
  
      return object;

})({});

document.getElementById("saida").innerHTML += object.method("teste") + "<br>";

// Não tem nenhum efeito (mas não lança nenhuma exceção!)
object.method = function() {
    return "Tentando mudar o método";
};

// Ainda chama o método antigo
document.getElementById("saida").innerHTML += object.method("teste");
<p id="saida"></p>

P.S. The case of jQuery that you mentioned behaves this way because the object returned by $(...) is not the same in one invocation and another:

var a = $('body');
var b = $('body');
a == b; // false

Also, if you replace a method in $.fn it becomes valid for all objects created from $(...):

$.fn.html = function() {
    alert("Método alterado!");
};

$('body').html(); // Chama o método sobrescrito
  • That one $.fn is the same thing as $.prototype, is not?

  • @Wallacemaxters I don’t think so (but I’m not sure). I believe that $.prototype would be the prototype of any object created with new $(...), but I’ve never seen any code do it that way. Have $.fn sets properties to any object created via $(...), but I don’t know if this is implemented internally as a prototype or as mixin. I’d have to check jQuery’s sources to be sure.

  • 1

    It’s because in jquery source code I’ve seen a stop like this: jQuery.fn = jQuery.prototype ... . So I thought it was :)

  • 1

    You’re right! When you call $(...) what happens underneath the covers is a new jQuery.fn.init(...), so that the prototype of the returned object is the init.prototype. However, in another part of the source I see that init.prototype = jQuery.fn; and, as fn is equal to prototype, then new $(...) must have the same practical result as $(...). It’s confusing, but anyway your statement is correct, both are the same thing.

0

'Cause when you do:

$('body').html = null
$('body').html()

You are calling the $ function separately so will always return a separate object.

  • 1

    But how to do not allow the superscript of the methods?

  • 2

    Why the negative vote? This answer is incomplete but correct (it explains why the superscript on one object does not affect the other object)

  • 1

    I was not the one who voted 'no', but perhaps you thought you were talking about the same thing that is already reported in the question. That’s what I thought when I saw it, so I didn’t give +1

Browser other questions tagged

You are not signed in. Login or sign up in order to post.