Crockford 的书《JavaScript:The Good Parts》(第 114 页)指出,构造函数的名称应始终以大写字母开头(即 Point),并且首字母大写的函数名称只能与构造函数一起使用(其他所有内容都应小写)。
这个约定帮助我们避免忘记在构造函数中使用 new 运算符。
他接着说,“更好的应对策略是根本不使用 new
。”
我的问题是,我们如何在不使用 new 的情况下编写 JavaScript 代码?代码>新根本吗?
- 我们可以使用文字
{}
和 []
来避免使用 new Object()
和 new Array()
。
- 我们可以使用
0
、< 来避免 new Number()
、new Boolean()
和 new String()
代码>true 和''
。
- 我们可以使用
/pattern/
之类的东西来避免 new RegExp()
。
我们如何避免new Date()
?
而且,最重要的是,我们如何避免将 new
与我们自己的自定义对象一起使用?
Crockford's book, JavaScript: The Good Parts, says (on page 114) that constructor functions should always be given names with an initial capital letter (ie. Point), and that function names with initial capital letters should only be used with constructor functions (everything else should be lowerCase).
This convention helps us avoid forgetting to use the new
operator with constructor functions.
He goes on to say that "[a]n even better coping strategy is to not use new
at all."
My question is, how do we program JavaScript without using new
at all?
- We can avoid
new Object()
and new Array()
with the literal {}
and []
.
- We can avoid
new Number()
, new Boolean()
, and new String()
with 0
, true
and ''
.
- We can avoid
new RegExp()
with something like /pattern/
.
How do we avoid new Date()
?
And, most importantly, how do we avoid using new
with our own custom Objects?
发布评论
评论(9)
Crockford 给出了一个对象创建函数的示例,该示例应该由 JS 本身在他的一次 Javascript 演讲中提供,该演讲位于 http://developer.yahoo.com/yui/theater/
然而,YUI(3) 团队本身使用“新”,并且他们确实遵循他的建议(因为他是雅虎首席 JS 架构师(更新:他继续前进,但是当这个回复最初写出来时,这个陈述是正确的)我理解这个特定的陈述更多地是在“学术”层面上,应该让语言设计得“正确”,而不是有一些剩余。他(恕我直言,正确地)说,JS 的方式是冲突的,基于原型,但与“经典类”继承语言的这一点
但是,JS 就是这样 。去使用“new”。
你可以在这里找到他的对象创建函数:http:// javascript.crockford.com/prototypal.html
编辑:更新为使用 Crockford 的该函数的最新版本 - 共有三个。
更新 2015 年 6 月:我们有
Object .create(...)
已经有一段时间了,当前所有浏览器都支持(包括IE 9及以上版本),所以不需要使用Crockford的函数。但是,事实证明,如果您使用
Object.create
,您应该确保不要经常这样做:该函数比使用慢得多新的构造函数()!
请参阅http://mrale.ph/blog/2014/07 /30/constructor-vs-objectcreate.html 了解说明(针对 V8 引擎),请参阅 http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/62 用于性能演示。
不拒绝
new Constructor(...)
的另一个原因是 ES6 类 肯定会得到广泛采用,即使只是因为大多数 Javascript 开发人员来自基于类的语言这一简单原因。另请查看这篇文章,其中支持
Object.create
:http://davidwalsh.name/javascript-objects-deconstruction不管你喜欢与否,尤其是在你想要与广泛的人分享的项目中(在空间和时间上——意思是正确或过度)时间,其他人接替你)使用
new
有更多理由。更新 2015 年 9 月:对于我自己来说,我已经开始在所有事情上使用 ES 2015 Javascript - 使用 io.js 和/或 Babel。除了
new Error(...)
之类的 Javascript 内置函数外,我的项目中也不使用任何new
。我更喜欢使用更强大的函数方法,我完全忽略对象系统。[my-object].prototype
和this
完全从我的项目中消失了。在很长一段时间里,我对这些想法非常怀疑,“因为对象工作得很好”。但在一个新的(io.js)项目开始时非常不情愿地尝试一下之后,它“点击”了,我不明白为什么我浪费了二十年。好吧,不完全是,今天的 JS 引擎和硬件更有利于这种风格。特别是对于 ES 2015,我建议提供一种完全不含任何this
和class
的函数式风格(新的 ES 2015 关键字或整个概念,基于使用constructorFn .prototype
)尝试一下。这可能需要你几个星期的时间,但一旦它“点击”,我保证你永远不会回去 - 不是自愿的。它更方便、更强大。更新 2018 年 2 月:虽然我仍然按照之前的更新中所写的内容进行操作,但现在我想补充一点,有时类是可以的。没有绝对的事情。 :-)
Crockford gives an example for an object creation function as should have been provided by JS itself in one of his Javascript talks available on http://developer.yahoo.com/yui/theater/
However, the YUI(3) team itself uses "new", and they DO follow his recommendations (since he's the Yahoo chief JS architect (UPDATE: he moved on, but the statement was true when this response was originally written). I understand this particular statement to be more on an "academic" level, what SHOULD have been HAD the language been designed "right" and not with some leftovers of the class-based inheritance stuff. He (IMHO rightly) says that the way it turned out JS is conflicted, prototype based but with this one thing from "classical class" inheritance languages.
However, JS is as it is so go and use "new".
You can find his object creation function here: http://javascript.crockford.com/prototypal.html
EDIT: Updated to use Crockford's latest version of that function - there are three.
UPDATE June 2015: We have had
Object.create(...)
for quite a while now, which all current browsers support (incl. IE 9 and above), so there was no need to use Crockford's function.However, it turns out that if you use
Object.create
you should make sure that you don't do that a lot: That function is FAR slower than usingnew Constructor()
!See http://mrale.ph/blog/2014/07/30/constructor-vs-objectcreate.html for an explanation (for the V8 engine), and see http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/62 for a performance demo.
Another reason to not turn your back on
new Constructor(...)
is that ES6 classes will surely see wide-ranging adoption even if only for the simple reason that most Javascript developers come from class-based languages.Also check out this article, which argues for
Object.create
: http://davidwalsh.name/javascript-objects-deconstructionLike it or not, especially in projects you want to share with a wide range of people (in space and time -- meaning right nor or over time, other people taking over from you) there are more reasons for using
new
.UPDATE September 2015: For myself, I have begun to use ES 2015 Javascript for everything - using either io.js and/or Babel. I also don't use any
new
in my projects except for the Javascript built-ins likenew Error(...)
. I prefer to use the far more powerful functional approach, I completely ignore the object system.[my-object].prototype
andthis
are completely gone from my projects. For the longest time I was VERY skeptical of these ideas "because objects work just fine". But after very reluctantly giving it a try at the beginning of a new (io.js) project it "clicked" and I don't understand why I wasted two decades. Okay, not quite, today the JS engines and hardware are much more conducive to that style. Especially with ES 2015, I recommend giving a functional style entirely free of anythis
andclass
(the new ES 2015 keyword or the entire concept, based on usingconstructorFn.prototype
) a try. It may take you a few weeks but once it "clicks" I promise you won't ever go back - not voluntarily. It's so much more convenient and more powerful.UPDATE February 2018: While I still do what I wrote in the previous update I now want to add that sometimes classes are fine. There are no absolutes. :-)
我也不知道如何避免
new Date()
或new XMLHttpRequest()
。但我确实知道如何避免对我自己的类型使用 new 。首先,我从
Object.create()
开始。这是 ES5 方法,因此并非在所有地方都可用。我使用 es5-shim 添加它,然后就可以开始了。我喜欢模块模式,所以我首先将我的类型包装在一个自动执行的匿名函数中,
var Xyz = (function() {...})()
。这意味着我有一个私人工作空间,而不会弄乱全局命名空间。我返回一个带有create()
函数和prototype
属性的对象。create()
函数适合我这种类型的用户。当他们需要一个时,他们会调用 Xyz.create(),并返回一个我类型的新的、初始化的对象。如果人们想要继承,则可以使用prototype
属性。这是一个例子:
继承看起来像这样:
I don't know how to avoid
new Date()
ornew XMLHttpRequest()
either. But I do know how to avoid using new for my own types.First, I start with
Object.create()
. This is an ES5 method, so it's not available everywhere. I add it using the es5-shim, ad then I'm ready to go.I like the module pattern, so I start by wrapping my type in a self-executing anonymous function,
var Xyz = (function() {...})()
. This means I have a private space to work without making a mess in the global namespace. I return an object with acreate()
function, and aprototype
property. thecreate()
function is for users of my type. When they want one, they callXyz.create()
, and get back a new, initialized object of my type. Theprototype
property is available if people want to inherit.Here's an example:
and inheritance looks like this:
不使用 new 并盲目追随 Crockford 是愚蠢的。
理解 JavaScript 并编写良好的代码。使用
new
关键字是 JavaScript OO 的基石。如果避免使用
new
,您将会错过很多优秀的 JavaScript 代码。不要随意从你的工具包中删除大量内容,而是学习它并正确使用它。
Crockford 习惯说 JavaScript 中任何给他的代码带来错误的东西都是不好的。
我个人会继续说“更好的应对策略就是有能力。”
Not using
new
and blindly following Crockford is silly.Understand JavaScript and write good code. Using the
new
keyword is the Cornerstone of JavaScript OO.You are going to miss out on a lot of good JavaScript code by avoiding
new
.Rather than arbitrarily cutting huge chunks out of your toolkit, learn it and use it properly instead.
Crockford has a habit of saying that anything in JavaScript which ever gave him a bug in his code is bad.
I would personally go on to say that "[a]n even better coping strategy is to be competent."
您可以通过创建工厂函数来避免
new
:(如果您想知道,您不能在工厂函数本身上避免它:)
尽管我认为只有在添加语义值(如上面的情况)或者可以默认某些构造函数参数时才应该创建这样的函数。换句话说,不要只是为了避免使用
new
而这样做。You can avoid
new
by creating factory functions:(In case you were wondering, you can't avoid it on the factory function itself:)
Although I only think you should create such functions if it adds semantic value (as in the case above) or if you can default some of the constructor parameters. In other words, don't do it just to avoid using
new
.这个问题已经被提出并回答: JavaScript 的“new”关键字被认为是有害的吗?
正如雷诺斯所说,盲目跟随克罗克福德(或其他任何人)而不理解他们为什么说他们所做的事情是愚蠢的。
This question has already been asked and answered: Is JavaScript's "new" keyword considered harmful?
As Raynos said, blindly following Crockford (or anyone else for that matter) without understanding why they say the things they do, is silly.
我认为他关于完全不使用 new 的建议是概念性的(学术性的),而不是从字面上理解。
Date
类是该规则的完美例外,因为否则如何使用标准 ECMAScript 获取当前(或任意)日期对象呢?但是,对于不将
new
与您自己的自定义对象一起使用,您可以使用一些策略。一种是使用类似工厂的方法而不是构造函数,构造函数可以将对象实例作为参数“祝福”到新类型中,或者默认使用新的对象文字。考虑以下几点:I think his advice of not using
new
at all is conceptual (academic) and not to be taken literally. TheDate
class is a perfect exception to the rule because how else can you get a current (or arbitrary) date object using standard ECMAScript?However, regarding not using
new
with your own custom objects you can use a few strategies. One is to use factory-like methods instead of constructors which could take as an argument an object instance to "bless" into your new type, or use a new object literal by default. Consider the following:您必须使用“new”来实例化其他人的对象。但对于您自己的代码,您可以避免“this”和“new”的陷阱。
(顺便说一句,问题确实不在于“new”本身。但是用“new”实例化的对象可能在内部使用“this”。使用“this”会导致频繁且微妙的错误,因为 javascript 的“this” ' 要求调用者做额外的工作来将被调用的方法绑定到正确的对象,并且不正确的绑定很难在运行前检测或以其他方式检测
。) 简短版本:
到 避免使用“new”来实例化您编写的对象,只需从任何函数返回一个对象即可。在该函数内,将任何方法附加到该对象并执行任何初始化。你已经完成了——该函数既是你的类定义又是构造函数。
长版本,例如:
以下“self”模式避免使用“new”和“this”。虽然该模式确实在每个对象中存储方法副本,但这并不重要,除非您在运行时创建大量对象。如果是这种情况,那么您始终可以使用 http://justjs 中的“flyweight”模式。 com/posts/this-considered-harmful。 (虽然该页面上的示例仍然使用了一点“this”,但也需要稍微调整一下以适应以下模式。)
You're stuck with using 'new' to instantiate other people's objects. But for your own code, you can avoid the pitfalls of both 'this' and 'new'.
(By the way, the issue really isn't with 'new' itself. But an object being instantiated with 'new' is probably using 'this' internally. Use of 'this' leads to frequent and subtle bugs, because javascript's 'this' requires the caller to do extra work to bind the called method to the right object, and incorrect bindings are hard to lint or otherwise detect before runtime.)
Short version:
To avoid using 'new' to instantiate objects you write, just return an object from any function. Inside that function, attach any methods to that object and do any initialization. You're done -- that function is both your class definition and constructor.
Long version, with example:
The following 'self' pattern avoids use of both 'new' and 'this'. While the pattern does store method copies in each object, this won't matter unless you're creating a lot of objects at runtime. If that's the case, then you can always use the 'flyweight' pattern from http://justjs.com/posts/this-considered-harmful. (While the examples on that page still use 'this' a little, it's a slight tweak to adapt those to the following pattern as well.)
您可以通过返回匿名对象并在构造函数中使用闭包来避免“new”。这也可以帮助您隐藏私人数据。
考虑一下:
现在要使用它,您所需要做的就是
这样做的好处是您不需要记住使用“new”,但如果您这样做,它不会伤害您。
You can avoid "new" by returning an anonymous object and using a closure in your constructor. This also help you hide private data.
Consider:
Now to use this, all you need to do is
The beauty of this is that you do not need to remember to use "new", but if you do it won't hurt you.