JavaScript:好的部分 - 如何不使用`new`

Rud*_*ger 57 javascript oop constructor new-operator

Crockford的书,JavaScript:The Good Parts,(第114页)说构造函数应始终给出带有首字母大写字母(即Point)的名称,并且带有首字母大写字母的函数名称只能与构造函数一起使用(其他一切都应该是lowerCase).

这个约定有助于我们避免忘记使用new构造函数的运算符.

他接着说,"更好的应对策略是根本不使用new."

我的问题是,我们如何编程JavaScript而不使用它new

  • 我们可以避免new Object()new Array()文字{}[].
  • 我们能够避免new Number(),new Boolean()以及new String()0,true''.
  • 我们可以避免new RegExp()类似的事情/pattern/.

我们如何避免new Date()

而且,最重要的是,我们如何避免使用new自己的自定义对象?

Mör*_*rre 41

Crockford给出了一个对象创建函数的例子,应该由JS本身在http://developer.yahoo.com/yui/theater/上提供的一个Javascript会话中提供.

然而,YUI(3)团队本身使用"新",他们遵循他的建议(因为他是雅虎首席JS架构师(更新:他继续前进,但是当最初编写此回复时声明是正确的.)我理解这个特别的陈述更多地是在"学术"层面,应该是什么,语言被设计为"正确",而不是基于类继承的东西的剩余.他(恕我直言)正确地说它的方式结果JS是冲突的,基于原型,但这一点来自"经典类"继承语言.

但是,JS就是这样,使用"新".

你可以在这里找到他的对象创建函数:http://javascript.crockford.com/prototypal.html

 if (typeof Object.create !== 'function') {
     Object.create = function (o) {
         function F() {}
         F.prototype = o;
         return new F();
     };
 }
 newObject = Object.create(oldObject);
Run Code Online (Sandbox Code Playgroud)


编辑:更新以使用Crockford的最新版本的功能 - 有三个.


更新 2015年6月:我们已经有Object.create(...)一段时间了,目前所有浏览器都支持(包括IE 9及更高版本),所以不需要使用Crockford的功能.

然而,事实证明,如果你使用Object.create你应该确保你没有做那么多:该功能比使用慢FAR new Constructor()!

有关说明(适用于V8引擎),请参见http://mrale.ph/blog/2014/07/30/constructor-vs-objectcreate.html,并参阅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.除了Javascript内置插件之外,我也不在我的项目中使用任何 .我更喜欢使用更强大的功能方法,我完全忽略了对象系统.并完全离开了我的项目.在最长的时间里,我对这些想法持怀疑态度"因为对象工作得很好".但是,在一个新的(io.js)项目开始时非常不情愿地尝试它"点击",我不明白为什么我浪费了二十年.好吧,不完全是,今天JS引擎和硬件更有利于这种风格.特别是随着2015年ES,我建议给人一种实用的风格完全没有任何与(新ES 2015年的关键字或整个概念的基础上,利用)一试.这可能需要几周的时间,但一旦"点击",我保证你永远不会回去 - 不是自愿的.它更方便,更强大.newnew Error(...)[my-object].prototypethisthisclassconstructorFn.prototype

更新 2018年2月:虽然我仍然按照我在上一次更新中所写的内容进行操作,但现在我想补充一点,有时类很好.没有绝对的.:-)

  • @Magrangs号我只是调用函数.存储在我存储在函数变量中的对象的状态 - 使用语言的(词法)作用域规则.如果外部需要访问我的内部状态,我用(仅)方法(在我的词法范围内,因此有访问权)回交一个对象,只是一个对象文字容器.这是必需的,因为函数只能有一个返回值.词法范围取代了对象. (3认同)

Sea*_*lan 12

我不知道如何避免new Date()new XMLHttpRequest()两种.但我确实知道如何避免为我自己的类型使用new.

首先,我开始Object.create().这是一种ES5方法,因此无处不在.我使用es5-shim添加它,广告然后我准备好了.

我喜欢模块模式,所以我首先将我的类型包装在一个自执行的匿名函数中var Xyz = (function() {...})().这意味着我有一个私有空间可以工作,而不会在全局命名空间中弄乱.我返回一个带有create()函数和prototype属性的对象.该create()功能适用于我的用户.当他们想要一个时,他们会调用Xyz.create(),然后返回一个新的,已初始化的类型对象.prototype如果人们想继承,酒店可以使用.

这是一个例子:

var Vehicle = (function(){
        var exports = {};
        exports.prototype = {};
        exports.prototype.init = function() {
                this.mph = 5;
        };
        exports.prototype.go = function() {
                console.log("Going " + this.mph.toString() + " mph.");
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports;
})();
Run Code Online (Sandbox Code Playgroud)

和继承看起来像这样:

var Car = (function () {
        var exports = {};
        exports.prototype = Object.create(Vehicle.prototype);
        exports.prototype.init = function() {
                Vehicle.prototype.init.apply(this, arguments);
                this.wheels = 4;
        };

        exports.create = function() {
                var ret = Object.create(exports.prototype);
                ret.init();
                return ret;
        };

        return exports; 

})();
Run Code Online (Sandbox Code Playgroud)


Ray*_*nos 11

不使用new和盲目跟随Crockford是愚蠢的.

理解JavaScript并编写好的代码.使用new关键字是JavaScript OO 的基石.

您将通过避免错过许多优秀的JavaScript代码new.

而不是从您的工具包中任意切割大块,而是学习并正确使用它.

Crockford有一种习惯,就是说JavaScript中的任何东西都给他带来了代码中的错误.

我个人会继续说"应该采取更好的应对策略."

  • 我不会说'new`是JavaScript OO的基石. (23认同)
  • @Raynos:我不同意; 虽然`{}`和`new Object()`具有相同的结果(一个新的空对象),但它们正是因为`{}`不使用`new`关键字.如果你有es5的`Object.create()`,那么你需要new的唯一时间是`Date`和`Error`(在核心JS中.你也需要它用于浏览器类型,但很少.)你可以写实用,组织良好的javascript,不使用`new`. (11认同)
  • @SeanMcMillan所以两个月后我同意,`new`很可怕,使用`Object.create` :) (8认同)
  • @Raynos:哦,当然,绝对.关注javascript中的`new`是关于缺乏判断一个函数是否需要`new`的能力,以及如果你忘记了`new`则在全局对象上运行构造函数的危险.对于全球职能部门的"这个"的破裂,可怜的"新"被指责. (3认同)
  • 呃......你拼错了"胜任":) (3认同)

Jor*_*dão 6

可以new通过创建工厂功能避免:

var today = Date.getToday();
Run Code Online (Sandbox Code Playgroud)

(如果你想知道,你无法避免它在工厂功能本身:)

Date.getToday = function() { return new Date(); };
Run Code Online (Sandbox Code Playgroud)

虽然我只认为你应该创建这样的函数,如果它添加了语义值(如上例所示)或者你可以默认一些构造函数参数.换句话说,不要只是为了避免使用new.

  • 特别为您自己的类型提供工厂。即使您必须使用“new”,也不要让您的客户使用它。 (2认同)

Ste*_*hen 5

这个问题已经被问及并回答:JavaScript的"新"关键字是否被视为有害?

正如雷诺斯所说,盲目跟随克罗克福德(或任何其他人)而不理解为什么他们说他们所做的事情,是愚蠢的.