When should I use my own namespace and when should I extend native js objects?
Asked Answered
S

5

9

I am in the process of refactoring my code. I'm having trouble deciding on how exactly to implement a couple utility functions I have. Specifically, if certain functions are better off in my personal namespace or extending js Objects directly.

Example of extending native JavaScript Objects

(is this the proper term?).

String.prototype.prettyDate = function(){
  return (this.substr(5,2) + '/' + this.substr(8) + '/' + this.substr(0,4));
}
var myString = "2010-12-27";
//logs 12/27/2010
console.log(myString.prettyDate);

Example using my own namespace

var myNamespace = (function(){
   var my = {};
   my.prettyDate = function ( dateStr ){
      return (dateStr.substr(5,2) + '/' + dateStr.substr(8) + '/' + dateStr.substr(0,4));
   }
return my;
}());
var pretifiedDate = myNamespace.prettyDate('2010-12-27');
//logs 12/27/2010
console.log(pretifiedDate);

Questions to consider

  1. When is a utility justifiably inserted into a native JavaScript Object?
  2. How can I tell when a utility is better off being in my own namespace?
Section answered 28/12, 2010 at 3:6 Comment(1)
This should have been a WIKI. The answer you accepted makes good points, but is very unfortunate in its conclusion. Just like any language feature, use it, but understand how/when to use it, and possible ramifications. Sometimes it is a good idea, sometimes perhaps not.Combine
H
7
  1. Almost never, because of:

    a/ possible conflicts with other libraries

    b/ extended functions are iterated as properties by in operator, which poses problems unless filtered out by hasOwnProperty (which is not commonly used)

    You can justify this for small, one-script works, but only if you 200% sure that no one, never ever will try to reuse that code somewhere. In such case use it only for functionality which spans more than one module of your code. Extending String with trim() - ok, extending String with prettyDate() - doubtful, extending Object with displayAsPageHeader() - scary.

  2. So, almost always.

Haggadah answered 28/12, 2010 at 3:19 Comment(6)
+1 for the problem with object iterations and in operator. :)Wondawonder
"possible conflicts" I'd think a developer would be aware of how the libraries utilized behave. "are iterated as properties by in" That's a good argument not to extend Object.prototype. Otherwise, shouldn't matter unless you do for/in over an Array, which is completely unnecessary. I think almost never/almost always is overstated.Combine
+1 but me personally, I would remove the "almost" in both statements.Lenardlenci
Been there, seen libraries which used every possible opportunity and very sophisticated techniques to block compatibility and interoperability. I've even seen global variable console declared once , so I prefer say it boldly: do not mess with prototype! And, of course, every generalisation is bad.Haggadah
@patrick dw: Saying "language feature X is unnecessary, therefore I don't care about supporting it" is not a very robust approach - someone will use it.Someday
@Piskvor: It is unnecessary because there are other ways to iterate, but there's no other way to extend a built-in class. But it is really even more that unnecessary. It is improper since it is not supported by the language to use for/in over an array with the expectation of only getting numeric indices. Extending a built-in class is a proper use of the language, which is being thrown out in favor of improper uses. How unfortunate.Combine
B
4

Watch this video:

John Resig reckons that extending native objects is a recipe for disaster, particularly when a framework or application is likely to grow into something that does far more than was initially intended.

Builtup answered 28/12, 2010 at 3:21 Comment(3)
Is he talking about extending DOM elements, or types like Array, String, etc.? Also, is it intended from the perspective of building a publicly used library, or in general?Combine
@patrick dw - I would say both. I watched that video a while back, and what stuck in my mind was 'okay, no more extending the prototype, unless it's a one-page simple app that will likely never change'. Apart from John R. looking extremely nervous, and his occasional uncomfortable and overly long pauses, the video is well worth the watch :)Builtup
I'll give it a watch eventually (thanks for the resource). I can see the arguments from the perspective of offering a widely distributed library. For personal use, my view is that's what prototype is for. Might as well use it. The exception being Object.prototype.Combine
H
2

Unfortunately, this question doesn't have a "right" answer. It's a good discussion to have but I fear it'll be closed here. Whether native objects should be extended at all is a subjective debate, and if you accept that it's conditionally okay the answer to "when?" is "depends."

If you have control over its use and whether it will collide with other code, there's really no reason you shouldn't. It can be quite convenient and may reduce code size significantly.

Where there's a real problem with extending native objects is when you have other code running alongside your extension, which may be expecting a different extension in with the same property name, or which may be carelessly using for(var i in obj) without guarding against extensions up the prototype chain.

Horotelic answered 28/12, 2010 at 3:21 Comment(1)
Or which may be deliberately using for (var i in obj) without checking hasOwnProperty because he thought he can make use of inheritance in javascript to compose objects.Lenardlenci
R
1

Ok... i'm not expert at this, but almost never! Things you do are safer inside your namespace. And everything works fine if you follow the module pattern http://www.yuiblog.com/blog/2007/06/12/module-pattern/

However theres are some little tricks that allows us to avoid to overwrite others namespace. per example:

var myNamespace = {}; //my namespace, unsafely written

//Better solution
if(typeof myNamespace === 'undefined'){
    var myNamespace = {};
}

//Shorter solution
var myNamespace = myNamespace || {};
Reprehensible answered 28/12, 2010 at 3:30 Comment(1)
You don't need === (strict equality comparison) to test typeof against a String.Horotelic
W
0

It depends on how much control you have over what code is being run/loaded:

  1. If it's all under your control there's nothing wrong with extending built-in objects, JavaScript is designed to be able to do this. The only problem with this is that you can have unexpected issues when two libraries change the same something. Luckily you wouldn't do this to yourself, right?

  2. If you don't/can't know, a namespace is much safer albeit clunky and verbose. This is always safer.

Personally, I prefer the second option because I dislike overly verbose code and namespaces look funny.

Wakerobin answered 28/12, 2010 at 4:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.