0

I found following prototype constructor (I call it create1) in "JavaScript: The Good Parts" book (page 22). Because author encourages against new keyword I tried to replicate this function without that keyword (create2). The obvious drawback is that it writes to 'protected' __proto__ property. But does it produce the same result? To my inspection yes, but I may be wrong. Why author choosed to use new here?

Object.create1 = function(o) { var F = function(){}; F.prototype = o; return new F(); };

Object.create2 = function(o) { var n = {}; n.__proto__ = o; return n; };

var proto = { number: 15, print: function () { return "number is " + this.number; } };
var _1 = Object.create1(proto);
var _2 = Object.create2(proto);
Pol
  • 5,064
  • 4
  • 32
  • 51
  • This is a polyfill. `Object.create` is already provided by all modern browsers. See here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create – elclanrs Feb 06 '14 at 23:12
  • Yes but still. My question may be considered theoretical. But I think it's useful. – Pol Feb 06 '14 at 23:14
  • 2
    In supporting engines, yes, the results will be the same. The difference is in compatibility -- `__proto__` is only marginally standardized (an available extra in ES6 drafts), has been deprecated in some engines that have supported it, and isn't supported at all in others. – Jonathan Lonowski Feb 06 '14 at 23:17

2 Answers2

3

Why author choosed to use new here?

Because it's absolutely necessary. One cannot create prototype chains without new, when Object.create is not available (and .__proto__ is non-standard).

Do not overvalue that he "encourages against new". The answer to Is JavaScript's "new" keyword considered harmful? is definitely No. There are instances where a pure Object.create is cleaner, and often enough new does confuse newbies, but once you know how it works you can - and should - use it. Whenever you need instance initialisation code, a constructor is completely fine.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • "Whenever you need instance initialisation code, a constructor is completely fine." - but then you can also use functional constructor (page 52). – Pol Feb 06 '14 at 23:32
  • @Pol: Yeah, but those don't provide inheritance (unless you use `var that=Object.create(…)`). With `new` you get both, without boilerplate code. – Bergi Feb 06 '14 at 23:46
  • If parent object can be created with functional constructor then you can just call that constructor inside child's constructor instead of using `Object.create`. – Pol Feb 06 '14 at 23:55
  • Okay, I should have said *prototypical* inheritance. Of course, you can always do [parasitic inheritance](http://www.crockford.com/javascript/inheritance.html) with a factory ("functional constructor"). – Bergi Feb 07 '14 at 00:13
1

When it comes to Douglas Crockford and his opinion of constructor functions I think you should carefully consider he is opinionated about the syntax. He doesn't like it and would come up with lots of patterns to avoid using it.

After the following presentation I would not put much weight on what he has to say about constructor functions:

http://www.youtube.com/watch?v=ya4UHuXNygM

At 51:30 he says "classical inheritance" is wrong because setting up prototype part of Child you have to create an instance of Parent. That's wrong, I agree but has nothing to do with the "classical" way because he corrects this in his "better" way by using Object.create. He could have used Object.create in the "classical" way to begin with and there'd be no need for the "better" way.

At 1:00;30 he claims Parent constructor code can't be re used in Child but I'm sure he knows about Parent.call(this.args); or does he? To use args in this way it does require you set up your functions to pass and receive arguments in a certain way. More info about this here under "Passing (constructor) arguments"

He complains about JavaScript trying to copy classical inheritance of Java but then continues complaining that the JavaScript style of defining constructor functions and prototype outside the constructor function doesn't look good (does it not look enough like Java?). There are benefits of being able to define your object over multiple files instead of having to put everything in one class/function/file.

Maybe Crockford is trolling because he does ask a couple of times "are you still with me" while he continues to destroy the prototype part of JavaScript until he ends up at 1:01:10 where he comes up with a pattern that doesn't use prototype at all (even though he praises JavaScript for having prototype and it being a great thing multiple times before that in this and the videos before this one).

I agree with the following: http://blog.millermedeiros.com/a-case-against-private-variables-and-functions-in-javascript/

Using privates is not useful. You need to indicate to developers that they should not use certain members then having an underscore in front of the name should do the trick. Other developers (and you) could still manipulate them if you have to. It's a risky thing because these members can be gone or re named in any update but it does allow you to test everything and test easier (even Java developers complain about the use of private). So Crockford's arguments for using the pattern at 1:01:00 that you have privates is not a valid point in my opinion and not liking the syntax was never a valid point as it has no technical merit.

In the link earlier posted I tried to explain how constructor functions and prototype works. I think it's important to know this before deciding it's bad and come up with patterns to work around it. Constructor functions and prototype can be hard to understand and even harder when people try to tell you to not use it and that it's wrong/out dated. A lot of documentation is incomplete or wrong (as with the example in the Crockford video) I think you should understand what it is and how to use it correctly first as it's a big part of how JavaScript works.

Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160
  • "Using privates is not useful. You need to indicate to developers that they should not use certain members then having an underscore in front of the name should do the trick." Not true. Have you read "Good parts" book? If not, please read it. It's short and fun. Otherwise thanks for long answer, I voted it up and I'll follow the links. – Pol Feb 07 '14 at 07:47
  • @Pol Thank you for your reply, I will read that book and did like the video but some of things in the video and on his blog are so wrong. What he calls "classical inheritance" he does wrong in every thing I've read and seen and then kicks it because of the things he does wrong. – HMR Feb 07 '14 at 10:55
  • @Pol I don't see a use for privates, to hide implementation you don't need to deny all access. It can save people some time to mock members for the sake of tests. To hide it for security is ridiculous since JavaScript does not have trusted sources as in .net and the box example I've seen doesn't prevent anyone from finding out what's inside. – HMR Feb 07 '14 at 10:57