Is JavaScript's “new” keyword considered harmful?

前端 未结 12 2052
情书的邮戳
情书的邮戳 2020-11-21 23:18

In another question, a user pointed out that the new keyword was dangerous to use and proposed a solution to object creation that did not use new.

相关标签:
12条回答
  • 2020-11-21 23:26

    I am newbie to Javascript so maybe I am just not too experienced in providing a good view point to this. Yet I want to share my view on this "new" thing.

    I have come from the C# world where using the keyword "new" is so natural that it is the factory design pattern that looks weird to me.

    When I first code in Javascript, I don't realize that there is the "new" keyword and code like the one in YUI pattern and it doesn't take me long to run into disaster. I lose track of what a particular line is supposed to be doing when looking back the code I've written. More chaotic is that my mind can't really transit between object instances boundaries when I am "dry-running" the code.

    Then, I found the "new" keyword which to me, it "separate" things. With the new keyword, it creates things. Without the new keyword, I know I won't confuse it with creating things unless the function I am invoking gives me strong clues of that.

    For instance, with var bar=foo(); I have no clues as what bar could possibly be.... Is it a return value or is it a newly created object? But with var bar = new foo(); I know for sure bar is an object.

    0 讨论(0)
  • 2020-11-21 23:29

    I wrote a post on how to mitigate the problem of calling a constructor without the new keyword.
    It's mostly didactic, but it shows how you can create constructors that work with or without new and doesn't require you to add boilerplate code to test this in every constructor.

    http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

    Here's the gist of the technique:

    /**
     * Wraps the passed in constructor so it works with
     * or without the new keyword
     * @param {Function} realCtor The constructor function.
     *    Note that this is going to be wrapped
     *    and should not be used directly 
     */
    function ctor(realCtor){
      // This is going to be the actual constructor
      return function wrapperCtor(){
        var obj; // object that will be created
        if (this instanceof wrapperCtor) {
          // Called with new
          obj = this;
        } else {
          // Called without new. Create an empty object of the
          // correct type without running that constructor
          surrogateCtor.prototype = wrapperCtor.prototype;
          obj = new surrogateCtor();
        }
        // Call the real constructor function
        realCtor.apply(obj, arguments);
        return obj;
      }
    
      function surrogateCtor() {}
    }
    

    Here's how to use it:

    // Create our point constructor
    Point = ctor(function(x,y){
      this.x = x;
      this.y = y;
    });
    
    // This is good
    var pt = new Point(20,30);
    // This is OK also
    var pt2 = Point(20,30);
    
    0 讨论(0)
  • 2020-11-21 23:32

    I agree with pez and some here.

    It seems obvious to me that "new" is self descriptive object creation, where the YUI pattern Greg Dean describes is completely obscured.

    The possibility someone could write var bar = foo; or var bar = baz(); where baz isn't an object creating method seems far more dangerous.

    0 讨论(0)
  • 2020-11-21 23:33

    Case 1: new isn't required and should be avoided

    var str = new String('asd');  // type: object
    var str = String('asd');      // type: string
    
    var num = new Number(12);     // type: object
    var num = Number(12);         // type: number
    

    Case 2: new is required, otherwise you'll get an error

    new Date().getFullYear();     // correct, returns the current year, i.e. 2010
    Date().getFullYear();         // invalid, returns an error
    
    0 讨论(0)
  • 2020-11-21 23:34

    I have just read some parts of his Crockfords book "Javascript: The Good Parts". I get the feeling that he considers everything that ever has bitten him as harmful:

    About switch fall through:

    I never allow switch cases to fall through to the next case. I once found a bug in my code caused by an unintended fall through immediately after having made a vigorous speech about why fall through was sometimes useful. (page 97, ISBN 978-0-596-51774-8)

    About ++ and --

    The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging exessive trickiness. They are second only to faulty architecture in enabling viruses and other security menaces. (page 122)

    About new:

    If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning. (page 49)

    There are more, but I hope you get the picture.

    My answer to your question: No, it's not harmful. but if you forget to use it when you should you could have some problems. If you are developing in a good environment you notice that.

    Update

    About a year after this answer was written the 5th edition of ECMAScript was released, with support for strict mode. In strict mode, this is no longer bound to the global object but to undefined.

    0 讨论(0)
  • 2020-11-21 23:36

    The rationale behind not using the new keyword, is simple:

    By not using it at all, you avoid the pitfall that comes with accidentally omitting it. The construction pattern that YUI uses, is an example of how you can avoid the new keyword altogether"

    var foo = function () {
        var pub= { };
        return pub;
    }
    var bar = foo();
    

    Alternatively you could so this:

    function foo() { }
    var bar = new foo();
    

    But by doing so you run risk of someone forgetting to use the new keyword, and the this operator being all fubar. AFAIK there is no advantage to doing this (other than you are used to it).

    At The End Of The Day: It's about being defensive. Can you use the new statement? Yes. Does it make your code more dangerous? Yes.

    If you have ever written C++, it's akin to setting pointers to NULL after you delete them.

    0 讨论(0)
提交回复
热议问题