Is JavaScript's “new” keyword considered harmf

2018-12-31 02:46发布

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. I didn't believe that was true, mostly because I've used Prototype, Scriptaculous and other excellent JavaScript libraries, and everyone of them used the new keyword.

In spite of that, yesterday I was watching Douglas Crockford's talk at YUI theater and he said the exactly same thing, that he didn't use the new keyword anymore in his code (Crockford on JavaScript - Act III: Function the Ultimate - 50:23 minutes).

Is it 'bad' to use the new keyword? What are the advantages and disadvantages of using it?

标签: javascript
12条回答
心情的温度
2楼-- · 2018-12-31 03:17

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);
查看更多
若你有天会懂
3楼-- · 2018-12-31 03:18

Another case for new is what I call Pooh Coding. Winnie the Pooh follows his tummy. I say go with the language you are using, not against it.

Chances are that the maintainers of the language will optimize the language for the idioms they try to encourage. If they put a new keyword into the language they probably think it makes sense to be clear when creating a new instance.

Code written following the language's intentions will increase in efficiency with each release. And code avoiding the key constructs of the language will suffer with time.

EDIT: And this goes well beyond performance. I can't count the times I've heard (or said) "why the hell did they do that?" when finding strange looking code. It often turns out that at the time when the code was written there was some "good" reason for it. Following the Tao of the language is your best insurance for not having your code ridiculed some years from now.

查看更多
萌妹纸的霸气范
4楼-- · 2018-12-31 03:19

Javascript being dynamic language there a zillion ways to mess up where another language would stop you.

Avoiding a fundamental language feature such as new on the basis that you might mess up is a bit like removing your shiny new shoes before walking through a minefield just in case you might get your shoes muddy.

I use a convention where function names begin with a lower case letter and 'functions' that are actually class definitions begin with a upper case letter. The result is a really quite compelling visual clue that the 'syntax' is wrong:-

var o = MyClass();  // this is clearly wrong.

On top of this good naming habits help. After all functions do things and therefore there should be a verb in its name whereas classes represent objects and are nouns and adjectives with no verb.

var o = chair() // Executing chair is daft.
var o = createChair() // makes sense.

Its interesting how SO's syntax colouring has interpretted the code above.

查看更多
临风纵饮
5楼-- · 2018-12-31 03:25

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.

查看更多
爱死公子算了
6楼-- · 2018-12-31 03:27

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.

查看更多
美炸的是我
7楼-- · 2018-12-31 03:28

I think new is evil, not because if you forget to use it by mistake it might cause problems but because it screws up the inheritance chain, making the language tougher to understand.

JavaScript is prototype-based object-oriented. Hence every object MUST be created from another object like so var newObj=Object.create(oldObj). Here oldObj is called the prototype of newObj (hence "prototype-based"). This implies that if a property is not found in newObj then it will be searched in oldObj. newObj by default will thus be an empty object but due to its prototype chain it appears to have all the values of oldObj.

On the other hand if you do var newObj=new oldObj(), the prototype of newObj is oldObj.prototype, which is unnecessarily difficult to understand.

The trick is to use

Object.create=function(proto){
  var F = function(){};
  F.prototype = proto;
  var instance = new F();
  return instance;
};

It is inside this function and only here that new should be used. After this simply use the Object.create() method. The method resolves the prototype problem.

查看更多
登录 后发表回答