‘壹’ v8引擎是如何知道js数据类型的
V8是谷歌开源的一个高性能javaScript引擎,用 C++ 实现,并用在谷歌的开源浏览器Chrome里。有些C/C++开发者有些奇怪的观念。他们认为使用面向对象和设计模式会降低程序的性能。但V8证明了这种观念是错误的。V8的实现使用了许多设计模式,但依然非常高效。观察者设计模式是将算法和算法处理的对象分开的一种方式。这种分离可以在不修改结构本身的情况下,将新的操作添加到已有的对象结构上。这是一条遵循open/closed准则的方式。
与工厂模式相似,访问者模式也为实现添加了封装层。这样让其代码更加可读且可维护。V8源码中许多类都实现了访问者模式。JavaScript是一种动态编程语言:可以在对象运行时为对象添加或删除熟悉。这意味着很容易改变对象的属性。JSFunction和JSValue的父类都是JSObject,JSFunction用来表示一个javascript函数,JSValue用来表示一个javascript值。但没有继承自JSObject的类,用以表示Function或Value这样的Class。许多JavaScript引擎使用词典类型的数据结构来存储这些对象的熟悉,访问每个属性都需要动态查找并解析属性在内存中的位置。这种方式导致JavaScript在访问对象变量的属性时,比在Java或Smalltalk中要慢。在这些语言中,实列变量分配的位置是固定的,即由编译器根据对象的类定义中的布局,在该对象在内存中的位置加上固定的偏移位置。因此访问这些属性仅仅是内存上的读取或存储,而这种操作通常只需一条指令。V8使用隐藏类概念来降低访问JavaScript属性所消耗的时间。V8不使用动态查询来访问属性,而是在幕后创建隐藏类。出于效率因素而不使用面向对象或设计模式,这是一个错误的观念。这样只会获得数毫秒的优化,却失去了代码的可读性和可维护性。
‘贰’ 下了chrome源码还要下JSV8源码么
您好,
虽然Chrome浏 览器没有完全解决内存尺寸问题,但是,它通过减少碎片来控制这个问题。在传统的浏览器中,浏览器为一个线程分配一套虚拟内存。当然,每一个标签都占用这个 总内存集中的一个内存块。随着你打开更多的标签,系统将分配更多的内存。但是,在你关闭标签的时候,内存没有完全恢复,不足以运行未来的标签。你最终将遇 到标准的内存碎片问题。
但是,在Chrome浏览器中,每一个标签都有自己的线程。你没有看错,不是每一个Chrome的窗口,而是每一个标签。Cogswell说,我做了20多年的开发工作。我从来没有看到一个窗口能够托管多个线程。但是,Chrome浏览器确实做到了。
Cogswell说,如果我目前的标签上有一个网页,我在地址栏输入一个新的URL地址的时候,与那个网页有关的chrome.exe命令请求就关闭了,并且开始一个新的chrome.exe命令请求。这样做是很完美的:不用输入命令清除分配给已经关闭的网页的内 存,Chrome浏览器将完全消除整个线程,然后开始一个新的线程。这是Chrome浏览器阻止内存碎片以及保护和隔离每一个网页的又一种方法。
更有趣的是在我装载雅虎网站www.yahoo.com的时候发现了一个奇怪的现象。我看到启动了两个线程。但是,对于谷歌搜索引擎 www.google.com那种比较小的网页,我仅看到了一个流程。当我查看命令行的时候我发现原来输入命令行参数设置了一个插件。那是一个叫做插件路 径的额外的参数,设置是c:/windows/system32/macromed/flash/npswf32.dll
那是Flash播放器。Chrome为嵌入在网页的Flash播放器启动了另一个线程。当我在Chrome浏览器 中保持雅虎网页处于打开状态并且关闭分配给Flash播放器的线程的时候,Chrome在雅虎网页上面显示一个提示并且用一个Flash标识取代了那个 Flash窗口,Flash标识上面有一个失望的面孔。
‘叁’ 如何编写Node.js插件
现在我们要做的是定义一个与JavaScript Object.prototype.constructor运作效果相同的方法:
v8::Handle STDStringWrapper::New(const v8::Arguments& args) {
我们首先需要为其创建一个范围:
v8::HandleScope scope;
在此之后,我们可以利用args对象的.IsConstructCall()方法来检查该构造函数是否能够利用new关键词加以调用:
if (args.IsConstructCall()) {
如果可以,我们首先如下所示将参数传递至std::string处:
v8::String::Utf8Value str(args[0]->ToString()); std::string s(*str);
……这样我们就能将它传递到我们封装类的构造函数当中了:
STDStringWrapper* obj = new STDStringWrapper(s);
在此之后,我们可以利用之前创建的该对象的.Wrap()方法(继承自node::ObjectWrap)来将它分配给this变量:
obj->Wrap(args.This());
最后,我们可以返回这个新创建的对象:
return args.This();
如果该函数无法利用new进行调用,我们也可以直接调用构造函数。接下来,我们要做的是为参数计数设置一个常数:
} else { const int argc = 1;
现在我们需要利用自己的参数创建一个数组:
v8::Local argv[argc] = { args[0] };
然后将constructor->NewInstance方法的结果传递至scope.Close,这样该对象就能在随后发挥作用(scope.Close基本上允许大家通过将对象处理句柄移动至更高范围的方式对其加以维持——这也是函数的起效方式):
return scope.Close(constructor->NewInstance(argc, argv)); } }
‘肆’ 如何查看javascript的源码
大名鼎鼎的Chrome浏览器的javascript引擎V8是开源的。你可以下载V8的源码看。
‘伍’ 求通达信公式高手将指标源码拆解成两个通达信选股公式,重酬
1、粉色柱出现第一天选股买入股票:
V1:=(C*2+H+L)/4*10;
V2:=EMA(V1,13)-EMA(V1,34);
V3:=EMA(V2,5);
V4:=2*(V2-V3)*5.5;
主力进:=IF(V4>=0,V4,0),COLORFF00FF;
V11:=3*SMA((C-LLV(L,55))/(HHV(H,55)-LLV(L,55))*100,5,1)-2*SMA(SMA((C-LLV(L,55))/(HHV(H,55)-LLV(L,55))*100,5,1),3,1);
趋势线:=EMA(V11,3);
XG:REF(主力进 AND 趋势线<13,1)=0 AND 主力进 AND 趋势线<13=1;
2、绿柱出现第一天预警卖出股票:
V8:=(INDEXC*2+INDEXH+INDEXL)/4;
V9:=EMA(V8,13)-EMA(V8,34);
VA:=EMA(V9,3);
VB:=(V9-VA)/2;
大盘资金撤走:=IF(VB<=0,VB,0),COLORGREEN;
V11:=3*SMA((C-LLV(L,55))/(HHV(H,55)-LLV(L,55))*100,5,1)-2*SMA(SMA((C-LLV(L,55))/(HHV(H,55)-LLV(L,55))*100,5,1),3,1);
趋势线:=EMA(V11,3);
卖出:REF(大盘资金撤走 AND 趋势线>90,1)=0 AND 大盘资金撤走 AND 趋势线>90=1;
不为别的,为了你的高分,必须滴!不许食言啊!
‘陆’ 我的Handle V8更新时断电了
按F8能用安全模式进入最好不过了,修复一次再去更新,如果安全模式无法进入,建议你重装系统了,有可能断电导致系统数据丢失!
‘柒’ v8是什么软件
Lars Bak是这个项目的组长,目前该JavaScript引擎已用于其它项目的开发。第一个版本随着第一个版本的Chrome于2008年9月2日发布。
V8使用C++开发,并在谷歌浏览器中使用。在运行JavaScript之前,相比其它的JavaScript的引擎转换成字节码或解释执行,V8将其编译成原生机器码(IA-32,x86-64,ARM, orMIPSCPUs),并且使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript程序在V8引擎下的运行速度媲美二进制程序。
V8中实现的ECMAScript中指定 ECMA - 262 ,第3版 运行在Windows XP和Vista,Mac OS X的10.5(雪豹和Linux系统使用IA - 32或ARM处理器。
V8可以独立运行,也可以 嵌入 到任何C++应用程序。项目托管在Google Code上,基于BSD协议,任何组织或个人可以将其源码用于自己的项目中。
‘捌’ 如何直接复制node
一、编写Node.js原生扩展Node.js是一个强大的平台,理想状态下一切都都可以用javascript写成。然而,你可能还会用到许多遗留的库和系统,这样的话使用c++编写Node.JS扩展会是一个不错的注意。以下所有例子的源代码可在node扩展示例中找到。编写Node.jsC++扩展很大程度上就像是写V8的扩展;Node.js增加了一些接口,但大部分时间你都是在使原始的V8数据类型和方法,为了理解以下的代码,你必须首先阅读V8引擎嵌入指南。Javascript版本的HelloWorld在讲解C++版本的例子之前,先让我们来看看在Node.js中用Javascript编写的等价模块是什么样子。这是一个最简单的HelloWorld,也不是通过HTTP,但它展示了node模块的结构,而其接口也和大多数C++扩展要提供的接口差不多:HelloWorldJs=function(){this.m_count=0;};HelloWorldJs.prototype.hello=function(){this.m_count++;return“HelloWorld”;};exports.HelloWorldJs=HelloWorldJs;正如你所看到的,它使用prototype为HelloWorldJs类创建了一个新的方法。请注意,上述代码通过将HelloWorldJS添加到exports变量来暴露构造函数。要在其他地方使用该模块,请使用如下代码:varhelloworld=require(‘helloworld_js’);varhi=newhelloworld.HelloWorldJs();console.log(hi.hello());//prints“HelloWorld”tostdoutC++版本的HelloWorld要开始编写C++扩展,首先要能够编译Node.js(请注意,我们使用的是Node.js2.0版本)。本文所讲内容应该兼容所有未来的0.2.x版本。一旦编译安装完node,编译模块就不在需要额外的东西了。完整的源代码可以在这里找到。在使用Node.js或V8之前,我们需要包括相关的头文件:#include#includeusingnamespacenode;usingnamespacev8;在本例子中我直接使用了V8和node的命名空间,使代码更易于阅读。虽然这种用法和谷歌的自己的C++编程风格指南相悖,但由于你需要不停的使用V8定义的类型,所以目前为止的大多数node的扩展仍然使用了V8的命名空间。接下来,声明HelloWorld类。它继承自node::ObjectWrap类,这个类提供了几个如引用计数、在V8内部传递contex等的实用功能。一般来说,所有对象应该继承ObjectWrap:classHelloWorld:ObjectWrap{private:intm_count;public:声明类之后,我们定义了一个静态成员函数,用来初始化对象并将其导入Node.js提供的target对象中。设个函数基本上是告诉Node.js和V8你的类是如何创建的,和它将包含什么方法:staticPersistents_ct;staticvoidInit(Handletarget){HandleScopescope;Localt=FunctionTemplate::New(New);s_ct=Persistent::New(t);s_ct->InstanceTemplate()->SetInternalFieldCount(1);s_ct->SetClassName(String::NewSymbol(“HelloWorld”));NODE_SET_PROTOTYPE_METHOD(s_ct,“hello”,Hello);target->Set(String::NewSymbol(“HelloWorld”),s_ct->GetFunction());}在上面这个函数中target参数将是模块对象,即你的扩展将要载入的地方。(译着:这个函数将你的对象及其方法连接到这个模块对象,以便外界可以访问)首先我们为New方法创建一个FunctionTemplate,将于稍后解释。我们还为该对象添加一个内部字段,并命名为HelloWorld。然后使用NODE_SET_PROTOTYPE_METHOD宏将hello方法绑定到该对象。最后,一旦我们建立好这个函数模板后,将他分配给target对象的HelloWorld属性,将类暴露给用户。接下来的部分是一个标准的C++构造函数:HelloWorld():m_count(0){}~HelloWorld(){}接下来,在::New方法中V8引擎将调用这个简单的C++构造函数:staticHandleNew(constArguments&args){HandleScopescope;HelloWorld*hw=newHelloWorld();hw->Wrap(args.This());returnargs.This();}此段代码相当于上面Javascript代码中使用的构造函数。它调用newHelloWorld创造了一个普通的C++对象,然后调用从ObjectWrap继承的Wrap方法,它将一个C++HelloWorld类的引用保存到args.This()的值中。在包装完成后返回args.This(),整个函数的行为和javascript中的new运算符类似,返回this指向的对象。现在我们已经建立了对象,下面介绍在Init函数中被绑定到hello的函数:staticHandleHello(constArguments&args){HandleScopescope;HelloWorld*hw=ObjectWrap::Unwrap(args.This());hw->m_count++;Localresult=String::New(“HelloWorld”);returnscope.Close(result);}函数中首先使用ObjectWrap模板的方法提取出指向HelloWorld类的指针,然后和javascript版本的HelloWorld一样递增计数器。我们新建一个内容为“HelloWorld”的v8字符串对象,然后在关闭本地作用域的时候返回这个字符串。上面的代码实际上只是针对v8的接口,最终我们还需要让Node.js知道如何动态加载我们的代码。为了使Node.js的扩展可以在执行时从动态链接库加载,需要有一个dlsym函数可以识别的符号,所以执行编写如下代码:extern“C”{staticvoidinit(Handletarget){HelloWorld::Init(target);}NODE_MODULE(helloworld,init);}由于c++的符号命名规则,我们使用externC,以便该符号可以被dysym识别。init方法是Node.js加载模块后第一个调用的函数,如果你有多个类型,请全部在这里初始化。NODE_MODULE宏用来填充一个用于存储模块信息的结构体,存储的信息如模块使用的API版本。这些信息可以用来防止未来因API不兼容导致的崩溃。到此,我们已经完成了一个可用的C++NodeJS扩展。Node.js也提供了一个用于构建模块的简单工具:node-waf首先编写一个包含扩展编译方法的wscript文件,然后执行node-wafconfigure&&node-wafbuild完成模块的编译和链接工作。对于这个helloworld的例子来说,wscript内容如下:defset_options(opt):opt.tool_options(“compiler_cxx”)defconfigure(conf):conf.check_tool(“compiler_cxx”)conf.check_tool(“node_addon”)defbuild(bld):obj=bld.new_task_gen(“cxx”,“shlib”,“node_addon”)obj.cxxflags=[“-g”,“-D_FILE_OFFSET_BITS=64”,“-D_LARGEFILE_SOURCE”,“-Wall”]obj.target=“helloworld”obj.source=“helloworld.cc”异步IO的HelloWorld对于实际的应用来说,HelloWorld的示例太过简单了一些,Node.js主要的优势是提供异步IO。Node.js内部通过libeio将会产生阻塞的操作全都放入线程池中执行。如果需要和遗留的c库交互,通常需要使用异步IO来为javascript代码提供回调接口。通常的模式是提供一个回调,在异步操作完成时被调用——你可以在整个Node.js的API中看到这种模式。Node.js的filesystem模块提供了一个很好的例子,其中大多数的函数都在操作完成后通过调用回调函数来传递数据。和许多传统的GUI框架一样,Node.js只在主线程中执行JavaScript,因此主线程以外的任何操作都不应该直接和V8或Javascript交互。同样helloworld_eio.cc源代码在GitHub上。我只强调和原来HelloWorld之间的差异,其中大部分代码保持不变,变化集中在Hello方法中:staticHandleHello(constArguments&args){HandleScopescope;REQ_FUN_ARG(0,cb);HelloWorldEio*hw=ObjectWrap::Unwrap(args.This());在Hello函数的入口处,我们使用宏从参数列表的第一个位置获取回调函数,在下一节中将详细介绍。然后,我们使用相同的Unwarp方法提取指向类对象的指针。hello_baton_t*baton=newhello_baton_t();baton->hw=hw;baton->increment_by=2;baton->sleep_for=1;baton->cb=Persistent::New(cb);这里我们创建一个baton结构,并将各种参数保存在里面。请注意,我们为回调函数创建了一个永久引用,因为我们想要在超出当前函数作用域的地方使用它。如果不这么做,在本函数结束后将无法再调用回调函数。hw->Ref();eio_custom(EIO_Hello,EIO_PRI_DEFAULT,EIO_AfterHello,baton);ev_ref(EV_DEFAULT_UC);returnUndefined();}如下代码是真正的重点。首先,我们增加HelloWorld对象的引用计数,这样在其他线程执行的时候他就不会被回收。函数eio_custom接受两个函数指针作为参数。EIO_Hello函数将在线程池中执行,然后EIO_AfterHello函数将回到在“主线程”中执行。我们的baton结构也被传递进各函数,这些函数可以使用baton结构中的数据完成相关的操作。同时,我们也增加eventloop的引用。这很重要,因为如果eventloop无事可做,Node.js就会退出。最终,函数返回Undefined,因为真正的工作将在其他线程中完成。staticintEIO_Hello(eio_req*req){hello_baton_t*baton=static_cast(req->data);sleep(baton->sleep_for);baton->hw->m_count+=baton->increment_by;return0;}这个回调函数将在libeio管理的线程中执行。首先,解析出baton结构,这样可以访问之前设置的各种参数。然后sheepbaton->sleep_for秒,这么做是安全的,因为这个函数运行在独立的线程中并不会阻塞主线程中javascript的执行。然后我们的增计数器,在实际的系统中,这些操作通常需要使用Lock/Mutex进行同步。当上述方法返回后,libeio将会通知主线程它需要在主线成上执行代码,此时EIO_AfterHello将会被调用。staticintEIO_AfterHello(eio_req*req){HandleScopescope;hello_baton_t*baton=static_cast(req->data);ev_unref(EV_DEFAULT_UC);baton->hw->Unref();进度此函数时,我们提取出baton结构,删除事件循环的引用,并减少HelloWorld对象的引用。Localargv[1];argv[0]=String::New(“HelloWorld”);TryCatchtry_catch;baton->cb->Call(Context::GetCurrent()->Global(),1,argv);if(try_catch.HasCaught()){FatalException(try_catch);}新建要传递给回调函数的字符串参数,并放入字符串数组中。然后我们调用回调传递一个参数,并检测可能抛出的异常。baton->cb.Dispose();deletebaton;return0;}在执行过回调之后,应该销毁持久引用,然后删除之前创建的baton结构。最后,你可以使用如下形式在Javascript中使用该模块:varhelloeio=require(‘./helloworld_eio’);hi=newhelloeio.HelloWorldEio();hi.hello(function(data){console.log(data);});参数传递与解析除了HelloWorld之外,你还需要理解最后一个问题:参数的处理。在helloWorldEIO例子中,我们使用一个REQ_FUN_ARG宏,然我们看看这个宏到底都做些什么。#defineREQ_FUN_ARG(I,VAR)\if(args.Length()IsFunction())\returnThrowException(Exception::TypeError(\String::New(“Argument”#I”mustbeafunction”)));\LocalVAR=Local::Cast(args[I]);就像Javascript中的argument变量,v8使用数组传递所有的参数。由于没有严格的类型限制,所以传递给函数的参数数目可能和期待的不同。为了对用户友好,使用如下的宏检测一下参数数组的长度并判断参数是否是正确的类型。如果传递了错误的参数类型,该宏将会抛出TypeError异常。为简化参数的解析,目前为止大多数的Node.js扩展都有一些本地作用域内的宏,用于特定类型参数的检测。二、揭秘node.js事件要使用NodeJS,你需要知道一个重要的东西:事件(events)。Node中有很多对象都可以触发事件,Node的文档中有很多示例。但文档也许并不能清晰的讲解如何编写自定义事件以及监听函数。对于一些简单的程序你可以不使用自定义事件,但这样很难应对复杂的应用。那么如何编写自定义事件?首先需要了解的是在node.js中的’events’模块。快速概览要访问此模块,只需使用如下语句:require(‘events’)requires(‘events’).EventEmitter特别说明,node中所有能触发事件的对象基本上都是后者的实例。让我们创建一个简单的演示程序Dummy:mmy.jsviewplaintoclipboardprint?//basicimportsvarevents=require(‘events’);//forustodoarequirelatermole.exports=Dummy;functionDummy(){events.EventEmitter.call(this);}10.11.//inheritevents.EventEmitter12.Dummy.super_=events.EventEmitter;13.Dummy.prototype=Object.create(events.EventEmitter.prototype,{14.constructor:{15.value:Dummy,16.enumerable:false17.}18.});//basicimportsvarevents=require(‘events’);//forustodoarequirelatermole.exports=Dummy;functionDummy(){events.EventEmitter.call(this);}//inheritevents.EventEmitterDummy.super_=events.EventEmitter;Dummy.prototype=Object.create(events.EventEmitter.prototype,{constructor:{value:Dummy,enumerable:false}});上述代码中重点展示如何使用EventEmitter扩充对象,并从中继承所有的原型对象,方法…等等。现在,我们假设Dummy有一个cooking()的方法,一旦把食物做熟之后它会触发’cooked’事件,并调用一个名为’eat’的回调函数。mmy-cooking.jsviewplaintoclipboardprint?Dummy.prototype.cooking=function(chicken){varself=this;self.chicken=chicken;self.cook=cook();//assumemmyfunctionthat’lldothecookingself.cook(chicken,function(cooked_chicken){self.chicken=cooked_chicken;self.emit(‘cooked’,self.chicken);});10.returnself;11.}Dummy.prototype.cooking=function(chicken){varself=this;self.chicken=chicken;self.cook=cook();//assumemmyfunctionthat’lldothecookingself.cook(chicken,function(cooked_chicken){self.chicken=cooked_chicken;self.emit(‘cooked’,self.chicken);});returnself;}
‘玖’ 搜猫搜索引擎 V8.5 V9.0 的源码,谁有,求好心人送我一套!求求各位了,草包站长用来建站的,拜托了各位了
虽然没有,先板凳下