( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法,要理解立即执行函数,需要先理解一些函数的基本概念。
函数声明:
function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明。
函数表达式:
var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。
匿名函数:
function () {}; 使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。
函数声明和函数表达式不同之处在于:
一、Javascript引擎在解析javascript代码时会‘函数声明提升'(Function declaration Hoisting)当前执行环境(作用域)上的函数声明。
而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式。
二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用。
在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式。
消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。
扩展资料
作用:
javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉。
根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”。
“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。
JQuery使用的就是这种方法,将JQuery代码包裹在( function (window,undefined){…jquery代码…} (window)中,在全局作用域中调用JQuery代码时,可以达到保护JQuery内部变量的作用。
JS语言特征(来自Pro Javascript Techniques)
1、引用
引用指向的只能是具体的对象,而不是另一个引用。在执行字符串链接 *** 作时,结果总会是一个新的字符串对象,而非原字符串的修改版本。
2、函数重载和类型检查
函数重载必须依赖两件事情:判断传入参数数量的能力和判断传入参数类型的能力。
1判断传入参数数量
JavaScript的每个函数都带有一个仅在这个函数范围内作用的变量(contextual variable)称为参数(argument),它是一个包含所有传给函数的参数的伪数组(pseudo-array),所以它并非真正意义的数组(也就是说你不能修改它,也不能用push()来添加新元素),但可以访问其中的元素,也具有length属性。
2判断传入参数类型
JavaScript的类型检查有两种特别有用的方法:
第一种方法是使用typeof *** 作符。这个工具提供了一个字符串名称,用于表达变量内容的类型。当变量不是object或array类型时,这是最完美的解决方法了。但是对于自定义的对象就不能用这个方法进行类型检查,因为它只返回object,很难跟其他的object区分开来。
第二种检查对象类型的方法,需要引用所有JavaScript对象都带有的一个属性,称为构造函数(construstor)。这个属性引用的是原本用来构造该对象的那个函数。
3、作用域
在Javascript里,作用域是由函数划分的,而不是由块(block)划分的。基于浏览器的Javascript的一个有趣特征是,所有属于全局作用域的变量其实都是window对象的属性。如果变量没有显式定义,它就是全局定义的,虽然它可能只在这个函数作用域的范围内使用。
闭包
闭包(closure)意味着内层的函数可以引用存在于包围它的函数内的变量,即使外层函数的执行已经终止。
闭包能实现的额外作用:
1、在一些函数式程序设计语言里,有一种称为Curry化的技术。本质上,Curry化是一种通过把多个参数填充到函数体中,实现将函数转换为一个新的经过简化的(使之接受参数更少)函数的技术。
function addGenerator(num)
{
//返回一个函数
return function(toAdd)
{
return num+toAdd;
};
}
var addFive=addGenerator(5);
aler(addFive(4)==9);
2、通过自执行的匿名函数你可以把所有原本属于全局的变量都隐藏起来。
(
function()
{
//这个变量如果没有用自执行的匿名函数包围起来那么它就是全局的
var msg="Thanks for visiting!";
windowonunload=funtion()
{
alert(msg);
};
}
)();
3、使用匿名函数来激发出创建多个使用闭包的函数所需的作用域
var obj=documentgetElementById("main");
var items=["click","keypress"];
for(var i=0;i<itemslength;i++)
{
(
function()
{
var item=item[i];
obj["on"+item]=funciton()
{
alert("Thanks for your "+item);
};
}
)();
}
4、上下文对象
在Javascript中,代码总是有一个上下文对象(代码处在该对象内)。上下文对象是通过this变量体现的,这个变量永远指向当前代码所处的对象中。全局对象其实是window对象的属性。这意味着即使是在全局上下文中,this变量也能指向一个对象。Javascript提供了call和apply两个方法,可以使用这两个方法改变上下文对象。
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:FengqiAsia
链接:http://wwwzhihucom/question/19653241/answer/15993549
来源:知乎
要讲清楚这个问题,先讲讲整个Web应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈。瓶颈在于服务器能够处理的并发连接的最大数量。Nodejs解决这个问题的方法是:更改连接到服务器的方式。每个连接发射一个在Nodejs引擎的进程中运行的事件,而不是为每个连接生成一个新的OS线程(并为其分配一些配套内存)。Nodejs不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用。Nodejs还宣称,运行它的服务器能支持数万个并发连接。
Node本身运行V8 JavaScript。V8 JavaScript引擎是Google用于其Chrome浏览器的底层JavaScript引擎。Google使用V8创建了一个用C++编写的超快解释器,该解释器拥有另一个独特特征:您可以下载该引擎并将其嵌入任何应用程序。V8 JavaScript引擎并不仅限于在一个浏览器中运行。因此,Nodejs实际上会使用Google编写的V8 JavaScript引擎,并将其重建为可在服务器上使用。
Nodejs优点:
1、采用事件驱动、异步编程,为网络服务而设计。其实Javascript的匿名函数和闭包特性非常适合事件驱动、异步编程。而且JavaScript也简单易学,很多前端设计人员可以很快上手做后端设计。
2、Nodejs非阻塞模式的IO处理给Nodejs带来在相对低系统资源耗用下的高性能与出众的负载能力,非常适合用作依赖其它IO资源的中间层服务。3、Nodejs轻量高效,可以认为是数据密集型分布式部署环境下的实时应用系统的完美解决方案。Node非常适合如下情况:在响应客户端之前,您预计可能有很高的流量,但所需的服务器端逻辑和处理不一定很多。
Nodejs缺点:
1、可靠性低
2、单进程,单线程,只支持单核CPU,不能充分的利用多核CPU服务器。一旦这个进程崩掉,那么整个web服务就崩掉了。
不过以上缺点可以可以通过代码的健壮性来弥补。目前Nodejs的网络服务器有以下几种支持多进程的方式:
#1 开启多个进程,每个进程绑定不同的端口,用反向代理服务器如 Nginx 做负载均衡,好处是我们可以借助强大的 Nginx 做一些过滤检查之类的 *** 作,同时能够实现比较好的均衡策略,但坏处也是显而易见——我们引入了一个间接层。
#2 多进程绑定在同一个端口侦听。在Nodejs中,提供了进程间发送“文件句柄” 的功能,这个功能实在是太有用了(貌似是yahoo 的工程师提交的一个patch) ,不明真相的群众可以看这里: Unix socket magic
#3 一个进程负责监听、接收连接,然后把接收到的连接平均发送到子进程中去处理。
在Nodejs v0510+ 中,内置了cluster 库,官方宣称直接支持多进程运行方式。Nodejs 官方为了让API 接口傻瓜化,用了一些比较tricky的方法,代码也比较绕。这种多进程的方式,不可避免的要牵涉到进程通信、进程管理之类的东西。
此外,有两个Nodejs的module:multi-node 和 cluster ,采用的策略和以上介绍的类似,但使用这些module往往有一些缺点:
#1 更新不及时
#2 复杂庞大,往往绑定了很多其他的功能,用户往往被绑架
#3 遇到问题难以解决
Node表现出众的典型示例包括:
1、RESTful API
提供RESTful API的Web服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合Node的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。
2、Twitter队列
想像一下像Twitter这样的公司,它必须接收tweets并将其写入数据库。实际上,每秒几乎有数千条tweet达到,数据库不可能及时处理高峰时段所需的写入数量。Node成为这个问题的解决方案的重要一环。如您所见,Node能处理数万条入站tweet。它能快速而又轻松地将它们写入一个内存排队机制(例如memcached),另一个单独进程可以从那里将它们写入数据库。Node在这里的角色是迅速收集tweet,并将这个信息传递给另一个负责写入的进程。想象一下另一种设计(常规PHP服务器会自己尝试处理对数据库本身的写入):每个tweet都会在写入数据库时导致一个短暂的延迟,因为数据库调用正在阻塞通道。由于数据库延迟,一台这样设计的机器每秒可能只能处理2000条入站tweet。每秒处理100万条tweet则需要500个服务器。相反,Node能处理每个连接而不会阻塞通道,从而能够捕获尽可能多的tweets。一个能处理50000条tweet的Node机器仅需20台服务器即可。
3、电子游戏统计数据
如果您在线玩过《使命召唤》这款游戏,当您查看游戏统计数据时,就会立即意识到一个问题:要生成那种级别的统计数据,必须跟踪海量信息。这样,如果有数百万玩家同时在线玩游戏,而且他们处于游戏中的不同位置,那么很快就会生成海量信息。Node是这种场景的一种很好的解决方案,因为它能采集游戏生成的数据,对数据进行最少的合并,然后对数据进行排队,以便将它们写入数据库。使用整个服务器来跟踪玩家在游戏中发射了多少子d看起来很愚蠢,如果您使用Apache这样的服务器,可能会有一些有用的限制;但相反,如果您专门使用一个服务器来跟踪一个游戏的所有统计数据,就像使用运行Node的服务器所做的那样,那看起来似乎是一种明智之举。
总的来说,Nodejs的应用场景
1) 适合
JSON APIs——构建一个Rest/JSON API服务,Nodejs可以充分发挥其非阻塞IO模型以及JavaScript对JSON的功能支持(如JSONstringfy函数)
单页面、多Ajax请求应用——如Gmail,前端有大量的异步请求,需要服务后端有极高的响应速度
基于Nodejs开发Unix命令行工具——Nodejs可以大量生产子进程,并以流的方式输出,这使得它非常适合做Unix命令行工具
流式数据——传统的Web应用,通常会将HTTP请求和响应看成是原子事件。而Nodejs会充分利用流式数据这个特点,构建非常酷的应用。如实时文件上传系统transloadit
准实时应用系统——如聊天系统、微博系统,但Javascript是有垃圾回收机制的,这就意味着,系统的响应时间是不平滑的(GC垃圾回收会导致系统这一时刻停止工作)。如果想要构建硬实时应用系统,Erlang是个不错的选择
2) 不适合
CPU使用率较重、IO使用率较轻的应用——如视频编码、人工智能等,Nodejs的优势无法发挥
简单Web应用——此类应用的特点是,流量低、物理架构简单,Nodejs无法提供像Ruby的Rails或者Python的Django这样强大的框架
NoSQL + Nodejs——如果仅仅是为了追求时髦,且自己对这两门技术还未深入理解的情况下,不要冒险将业务系统搭建在这两个漂亮的名词上,建议使用MySQL之类的传统数据库
如果系统可以匹配Nodejs的适用场景,那么是时候采取具体的措施来说服老板了。
说服自己老板采用Nodejs的方式
构建一个简单的原型——花一周时间构建系统某一部分的原型是非常值得的,同时也很容易和老板在某一点达成一致,等到系统真的在某一部分应用了Nodejs,就是打开局面的时候
寻找开发者——首先JavaScript语言的普及度很高,一般公司都不乏Web前端工程师,而此类工程师的学习门槛也非常低。这就意味着Nodejs很容易招人,或者公司就隐藏了一些高手
强大的社区支持——Nodejs社区非常活跃,吸引很多优秀的工程师,这就意味着公司可以很容易从社区得到免费或者付费的支持
系统性能考虑——JavaScript引擎Google V8,加之原生异步IO模型,使得Nodejs在性能的表现非常出色,处理数以千计的并发请求非常轻松
专业公司的支持——使用开源技术的最大问题是,原作者不承诺对其产品进行技术支持或者质量保证。现在Nodejs已经得到Joyent公司的赞助,这就保证了未来Nodejs的发展是可持续性的
这里不一定是需要匿名函数, 可以直接把函数赋值给onmouseover的例如
function move(e){alert(etype);
}
eleonmouseover = move;
但是你这里的写法不对
你第一句的写法, 是将moveElement这个函数的返回值赋给onmouseover, 这样就会出现错误
事件监听, 必须是一个函数,
不知道这样说, 你能不能理解,
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)