在 JavaScript 中,一个通常被吹捧的良好性能原则是避免改变对象的形状。
这让我想知道,这是不是
class Foo {
constructor() {
this.bar = undefined;
}
baz(x) { this.bar = x; }
}
一个有值(value)的最佳实践,将提供比这更好的性能
class Foo {
constructor() {
}
baz(x) { this.bar = x; }
}
这是真的还是假的?为什么?在一个 JS 引擎中是否比其他引擎更真实或更不真实?
最佳答案
这里是 V8 开发人员。
是的,总的来说,第一个版本是一个有值(value)的最佳实践。
这样做的原因是不是对象创建本身会更快。相反,很明显,不做任何工作的构造函数至少比做一些工作的构造函数快一点。
推荐第一个版本的原因是因为它确保应用程序中的所有 Foo 对象都具有相同的“形状”,而对于第二个版本,它们中的一些可能具有相同的“形状” .bar 属性,其他则没有。有时存在有时不存在的属性往往会迫使 JavaScript 引擎远离它可以使用的最快可能状态/代码路径;当有多个这样的属性时,效果会大得多。
举个例子:
class Foo() {
constructor() {}
addBar(x) { this.bar = x; }
addBaz(x) { this.baz = x; }
addQux(x) { this.qux = x; }
}
var foo1 = new Foo(); foo1.addBar(1);
var foo2 = new Foo(); foo2.addBaz(10); foo2.addBar(2);
var foo3 = new Foo(); foo3.addQux(100); foo3.addBaz(20); foo3.addBar(3);
function hot_function(foo) {
return foo.bar; // [1]
}
hot_function(foo1);
hot_function(foo2);
hot_function(foo3);
在标记为 [1] 的行中,使用此版本的构造函数,可以看到至少三种不同形状的对象。因此,JavaScript 引擎将在对象内的至少三个不同位置找到属性 bar。根据其内部实现细节,它可能每次都必须搜索所有对象的属性,或者它可以缓存它以前见过的对象形状,但缓存多个比缓存一个更昂贵,并且缓存尝试会有限制.
但是,如果构造函数将所有属性初始化为 undefined,那么所有传入的 foo 对象都将具有相同的形状,并且 bar 属性将始终是他们的第一个属性,引擎可以使用非常快速的代码来处理这种非常简单的情况。
不仅仅是这样的负载:addBar() 的幕后工作也会有所不同,具体取决于它是否可以简单地覆盖现有属性(非常快),是否必须添加新属性(可能慢得多,可能需要分配和复制对象),或者必须在这两种情况之间动态做出决定(当然是最慢的)。
另一个影响是每个独特的对象形状都需要一定数量的内部元数据。因此,避免不必要的不同对象形状将节省一些内存。
当然对于这么小的例子,任何影响都是小的。但是一旦你拥有一个包含数千个对象的大型应用程序,每个对象都有几十个属性,它就会产生很大的不同。谨防误导性微基准测试!
关于javascript - 鉴于 V8/spidermonkey/chakra 的内部工作原理,在 JavaScript 中显式初始化 undefined object 成员是否是一种优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44466931/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到rubygems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下